From d0a53d17607e9af841e88a2b834b69559d17432a Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 29 May 2020 06:09:26 +0200 Subject: [PATCH] Handle starting the frontend before finished loading integrations (#6068) Co-authored-by: J. Nick Koston --- package.json | 2 +- src/fake_data/demo_config.ts | 3 +- src/layouts/partial-panel-resolver.ts | 31 +++++++ src/mixins/subscribe-mixin.ts | 6 +- .../lovelace/badges/hui-state-label-badge.ts | 1 - .../lovelace/cards/hui-alarm-panel-card.ts | 12 +-- src/panels/lovelace/cards/hui-button-card.ts | 12 +-- src/panels/lovelace/cards/hui-entity-card.ts | 12 +-- src/panels/lovelace/cards/hui-gauge-card.ts | 12 +-- src/panels/lovelace/cards/hui-glance-card.ts | 7 +- src/panels/lovelace/cards/hui-light-card.ts | 12 +-- .../lovelace/cards/hui-media-control-card.ts | 12 +-- .../lovelace/cards/hui-picture-entity-card.ts | 12 +-- .../lovelace/cards/hui-picture-glance-card.ts | 7 +- .../lovelace/cards/hui-plant-status-card.ts | 11 +-- .../lovelace/cards/hui-starting-card.ts | 86 +++++++++++++++++++ .../lovelace/cards/hui-thermostat-card.ts | 12 +-- .../cards/hui-weather-forecast-card.ts | 12 +-- .../common/generate-lovelace-config.ts | 23 +++++ src/panels/lovelace/common/has-changed.ts | 7 +- .../components/hui-generic-entity-row.ts | 12 +-- .../components/hui-warning-element.ts | 2 +- src/panels/lovelace/components/hui-warning.ts | 15 ++++ .../create-element/create-card-element.ts | 1 + .../elements/hui-state-badge-element.ts | 7 +- .../elements/hui-state-icon-element.ts | 7 +- .../elements/hui-state-label-element.ts | 7 +- .../entity-rows/hui-climate-entity-row.ts | 12 +-- .../entity-rows/hui-cover-entity-row.ts | 12 +-- .../entity-rows/hui-group-entity-row.ts | 12 +-- .../hui-input-datetime-entity-row.ts | 11 +-- .../hui-input-number-entity-row.ts | 12 +-- .../hui-input-select-entity-row.ts | 12 +-- .../entity-rows/hui-input-text-entity-row.ts | 12 +-- .../entity-rows/hui-lock-entity-row.ts | 12 +-- .../hui-media-player-entity-row.ts | 12 +-- .../entity-rows/hui-scene-entity-row.ts | 12 +-- .../entity-rows/hui-script-entity-row.ts | 12 +-- .../entity-rows/hui-sensor-entity-row.ts | 12 +-- .../entity-rows/hui-text-entity-row.ts | 12 +-- .../entity-rows/hui-timer-entity-row.ts | 12 +-- .../entity-rows/hui-toggle-entity-row.ts | 12 +-- .../entity-rows/hui-weather-entity-row.ts | 12 +-- src/panels/lovelace/ha-panel-lovelace.ts | 9 +- .../special-rows/hui-attribute-row.ts | 12 +-- src/state/connection-mixin.ts | 8 ++ src/state/disconnect-toast-mixin.ts | 33 +++++++ src/translations/en.json | 9 +- yarn.lock | 8 +- 49 files changed, 352 insertions(+), 261 deletions(-) create mode 100644 src/panels/lovelace/cards/hui-starting-card.ts diff --git a/package.json b/package.json index 198495a396..32f5d1fe8d 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "fuse.js": "^6.0.0", "google-timezones-json": "^1.0.2", "hls.js": "^0.12.4", - "home-assistant-js-websocket": "^5.1.2", + "home-assistant-js-websocket": "^5.2.1", "idb-keyval": "^3.2.0", "intl-messageformat": "^8.3.9", "js-yaml": "^3.13.1", diff --git a/src/fake_data/demo_config.ts b/src/fake_data/demo_config.ts index e1d342e45a..86b5484b33 100644 --- a/src/fake_data/demo_config.ts +++ b/src/fake_data/demo_config.ts @@ -1,4 +1,4 @@ -import { HassConfig } from "home-assistant-js-websocket"; +import { HassConfig, STATE_RUNNING } from "home-assistant-js-websocket"; export const demoConfig: HassConfig = { location_name: "Home", @@ -18,6 +18,7 @@ export const demoConfig: HassConfig = { whitelist_external_dirs: [], config_source: "storage", safe_mode: false, + state: STATE_RUNNING, internal_url: "http://homeassistant.local:8123", external_url: null, }; diff --git a/src/layouts/partial-panel-resolver.ts b/src/layouts/partial-panel-resolver.ts index 89b018bb84..0b766f697f 100644 --- a/src/layouts/partial-panel-resolver.ts +++ b/src/layouts/partial-panel-resolver.ts @@ -8,6 +8,11 @@ import { RouteOptions, RouterOptions, } from "./hass-router-page"; +import { + STATE_STARTING, + STATE_NOT_RUNNING, + STATE_RUNNING, +} from "home-assistant-js-websocket"; const CACHE_URL_PATHS = ["lovelace", "developer-tools"]; const COMPONENTS = { @@ -84,6 +89,8 @@ class PartialPanelResolver extends HassRouterPage { @property() public narrow?: boolean; + private _waitForStart = false; + protected updated(changedProps: PropertyValues) { super.updated(changedProps); @@ -93,6 +100,15 @@ class PartialPanelResolver extends HassRouterPage { const oldHass = changedProps.get("hass") as this["hass"]; + if ( + this._waitForStart && + (this.hass.config.state === STATE_STARTING || + this.hass.config.state === STATE_RUNNING) + ) { + this._waitForStart = false; + this.rebuild(); + } + if (this.hass.panels && (!oldHass || oldHass.panels !== this.hass.panels)) { this._updateRoutes(oldHass?.panels); } @@ -128,6 +144,21 @@ class PartialPanelResolver extends HassRouterPage { private async _updateRoutes(oldPanels?: HomeAssistant["panels"]) { this.routerOptions = getRoutes(this.hass.panels); + if ( + !this._waitForStart && + this._currentPage && + !this.hass.panels[this._currentPage] + ) { + if (this.hass.config.state !== STATE_NOT_RUNNING) { + this._waitForStart = true; + if (this.lastChild) { + this.removeChild(this.lastChild); + } + this.appendChild(this.createLoadingScreen()); + return; + } + } + if ( !oldPanels || !deepEqual( diff --git a/src/mixins/subscribe-mixin.ts b/src/mixins/subscribe-mixin.ts index 3250093763..466e945af3 100644 --- a/src/mixins/subscribe-mixin.ts +++ b/src/mixins/subscribe-mixin.ts @@ -24,7 +24,11 @@ export const SubscribeMixin = >( if (this.__unsubs) { while (this.__unsubs.length) { const unsub = this.__unsubs.pop()!; - Promise.resolve(unsub).then((unsubFunc) => unsubFunc()); + if (unsub instanceof Promise) { + unsub.then((unsubFunc) => unsubFunc()); + } else { + unsub(); + } } this.__unsubs = undefined; } diff --git a/src/panels/lovelace/badges/hui-state-label-badge.ts b/src/panels/lovelace/badges/hui-state-label-badge.ts index 501e9cd185..e87eb1126d 100644 --- a/src/panels/lovelace/badges/hui-state-label-badge.ts +++ b/src/panels/lovelace/badges/hui-state-label-badge.ts @@ -14,7 +14,6 @@ import { HomeAssistant } from "../../../types"; import { actionHandler } from "../common/directives/action-handler-directive"; import { handleAction } from "../common/handle-action"; import { hasAction } from "../common/has-action"; -import "../components/hui-warning-element"; import { LovelaceBadge } from "../types"; import { StateLabelBadgeConfig } from "./types"; diff --git a/src/panels/lovelace/cards/hui-alarm-panel-card.ts b/src/panels/lovelace/cards/hui-alarm-panel-card.ts index 5cb59213a3..77de911dc8 100644 --- a/src/panels/lovelace/cards/hui-alarm-panel-card.ts +++ b/src/panels/lovelace/cards/hui-alarm-panel-card.ts @@ -22,7 +22,7 @@ import { } from "../../../data/alarm_control_panel"; import type { HomeAssistant } from "../../../types"; import { findEntities } from "../common/find-entites"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import type { LovelaceCard } from "../types"; import { AlarmPanelCardConfig } from "./types"; @@ -151,13 +151,9 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/cards/hui-button-card.ts b/src/panels/lovelace/cards/hui-button-card.ts index 454f572290..ce7d18e3de 100644 --- a/src/panels/lovelace/cards/hui-button-card.ts +++ b/src/panels/lovelace/cards/hui-button-card.ts @@ -33,7 +33,7 @@ import { actionHandler } from "../common/directives/action-handler-directive"; import { findEntities } from "../common/find-entites"; import { handleAction } from "../common/handle-action"; import { hasAction } from "../common/has-action"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { LovelaceCard, LovelaceCardEditor } from "../types"; import { ButtonCardConfig } from "./types"; @@ -145,13 +145,9 @@ export class HuiButtonCard extends LitElement implements LovelaceCard { if (this._config.entity && !stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/cards/hui-entity-card.ts b/src/panels/lovelace/cards/hui-entity-card.ts index 449380b053..bc5f9e9364 100644 --- a/src/panels/lovelace/cards/hui-entity-card.ts +++ b/src/panels/lovelace/cards/hui-entity-card.ts @@ -20,7 +20,7 @@ import { UNAVAILABLE_STATES } from "../../../data/entity"; import { HomeAssistant } from "../../../types"; import { findEntities } from "../common/find-entites"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { createHeaderFooterElement } from "../create-element/create-header-footer-element"; import { LovelaceCard, @@ -92,13 +92,9 @@ export class HuiEntityCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/cards/hui-gauge-card.ts b/src/panels/lovelace/cards/hui-gauge-card.ts index 37d9f761af..c8917be4ef 100644 --- a/src/panels/lovelace/cards/hui-gauge-card.ts +++ b/src/panels/lovelace/cards/hui-gauge-card.ts @@ -20,7 +20,7 @@ import "../../../components/ha-card"; import type { HomeAssistant } from "../../../types"; import { findEntities } from "../common/find-entites"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import type { LovelaceCard, LovelaceCardEditor } from "../types"; import type { GaugeCardConfig } from "./types"; import { debounce } from "../../../common/util/debounce"; @@ -105,13 +105,9 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/cards/hui-glance-card.ts b/src/panels/lovelace/cards/hui-glance-card.ts index 063d29c41d..30442ebfc9 100644 --- a/src/panels/lovelace/cards/hui-glance-card.ts +++ b/src/panels/lovelace/cards/hui-glance-card.ts @@ -30,6 +30,7 @@ import "../components/hui-warning-element"; import { LovelaceCard, LovelaceCardEditor } from "../types"; import "../components/hui-timestamp-display"; import { GlanceCardConfig, GlanceConfigEntity } from "./types"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; @customElement("hui-glance-card") export class HuiGlanceCard extends LitElement implements LovelaceCard { @@ -212,11 +213,7 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` `; } diff --git a/src/panels/lovelace/cards/hui-light-card.ts b/src/panels/lovelace/cards/hui-light-card.ts index 0fdf7f191e..b45d14cb1a 100644 --- a/src/panels/lovelace/cards/hui-light-card.ts +++ b/src/panels/lovelace/cards/hui-light-card.ts @@ -28,7 +28,7 @@ import { findEntities } from "../common/find-entites"; import { handleAction } from "../common/handle-action"; import { hasAction } from "../common/has-action"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { LovelaceCard, LovelaceCardEditor } from "../types"; import { LightCardConfig } from "./types"; @@ -89,13 +89,9 @@ export class HuiLightCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/cards/hui-media-control-card.ts b/src/panels/lovelace/cards/hui-media-control-card.ts index 340689a843..4059abdf48 100644 --- a/src/panels/lovelace/cards/hui-media-control-card.ts +++ b/src/panels/lovelace/cards/hui-media-control-card.ts @@ -44,7 +44,7 @@ import { findEntities } from "../common/find-entites"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-marquee"; import type { LovelaceCard, LovelaceCardEditor } from "../types"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { MediaControlCardConfig } from "./types"; import { installResizeObserver } from "../common/install-resize-observer"; @@ -266,13 +266,9 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/cards/hui-picture-entity-card.ts b/src/panels/lovelace/cards/hui-picture-entity-card.ts index 16d24baf33..c8bc0e593b 100644 --- a/src/panels/lovelace/cards/hui-picture-entity-card.ts +++ b/src/panels/lovelace/cards/hui-picture-entity-card.ts @@ -24,7 +24,7 @@ import { handleAction } from "../common/handle-action"; import { hasAction } from "../common/has-action"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-image"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { LovelaceCard, LovelaceCardEditor } from "../types"; import { PictureEntityCardConfig } from "./types"; @@ -116,13 +116,9 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/cards/hui-picture-glance-card.ts b/src/panels/lovelace/cards/hui-picture-glance-card.ts index e1b6c22f91..d298d79c52 100644 --- a/src/panels/lovelace/cards/hui-picture-glance-card.ts +++ b/src/panels/lovelace/cards/hui-picture-glance-card.ts @@ -30,6 +30,7 @@ import "../components/hui-image"; import "../components/hui-warning-element"; import { LovelaceCard, LovelaceCardEditor } from "../types"; import { PictureGlanceCardConfig, PictureGlanceEntityConfig } from "./types"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; const STATES_OFF = new Set(["closed", "locked", "not_home", "off"]); @@ -229,11 +230,7 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` `; } diff --git a/src/panels/lovelace/cards/hui-plant-status-card.ts b/src/panels/lovelace/cards/hui-plant-status-card.ts index 1efc825119..304e0f65ec 100644 --- a/src/panels/lovelace/cards/hui-plant-status-card.ts +++ b/src/panels/lovelace/cards/hui-plant-status-card.ts @@ -20,6 +20,7 @@ import { findEntities } from "../common/find-entites"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import { LovelaceCard, LovelaceCardEditor } from "../types"; import { PlantAttributeTarget, PlantStatusCardConfig } from "./types"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; const SENSORS = { moisture: "hass:water", @@ -105,13 +106,9 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/cards/hui-starting-card.ts b/src/panels/lovelace/cards/hui-starting-card.ts new file mode 100644 index 0000000000..fc554d74e4 --- /dev/null +++ b/src/panels/lovelace/cards/hui-starting-card.ts @@ -0,0 +1,86 @@ +import "@material/mwc-button/mwc-button"; +import { + css, + CSSResult, + customElement, + html, + LitElement, + property, + TemplateResult, + PropertyValues, +} from "lit-element"; +import "../../../components/ha-card"; +import { HomeAssistant } from "../../../types"; +import { LovelaceCard } from "../types"; +import { LovelaceCardConfig } from "../../../data/lovelace"; +import "@polymer/paper-spinner/paper-spinner-lite"; +import { fireEvent } from "../../../common/dom/fire_event"; +import { STATE_STARTING, STATE_RUNNING } from "home-assistant-js-websocket"; + +@customElement("hui-starting-card") +export class HuiStartingCard extends LitElement implements LovelaceCard { + @property() public hass?: HomeAssistant; + + public getCardSize(): number { + return 2; + } + + public setConfig(_config: LovelaceCardConfig): void { + // eslint-disable-next-line + } + + protected updated(changedProperties: PropertyValues) { + super.updated(changedProperties); + if (!changedProperties.has("hass") || !this.hass!.config) { + return; + } + + const oldHass = changedProperties.get("hass") as HomeAssistant | undefined; + + if ( + (!oldHass?.config || oldHass.config.state !== this.hass!.config.state) && + (this.hass!.config.state === STATE_STARTING || + this.hass!.config.state === STATE_RUNNING) + ) { + fireEvent(this, "config-refresh"); + } + } + + protected render(): TemplateResult { + if (!this.hass) { + return html``; + } + + return html` +
+ + ${this.hass.localize("ui.panel.lovelace.cards.starting.description")} +
+ `; + } + + static get styles(): CSSResult { + return css` + :host { + display: block; + height: calc(100vh - 64px); + } + paper-spinner-lite { + padding-bottom: 20px; + } + .content { + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-starting-card": HuiStartingCard; + } +} diff --git a/src/panels/lovelace/cards/hui-thermostat-card.ts b/src/panels/lovelace/cards/hui-thermostat-card.ts index 7ddb744caa..5959b4decb 100644 --- a/src/panels/lovelace/cards/hui-thermostat-card.ts +++ b/src/panels/lovelace/cards/hui-thermostat-card.ts @@ -29,7 +29,7 @@ import { HomeAssistant } from "../../../types"; import { actionHandler } from "../common/directives/action-handler-directive"; import { findEntities } from "../common/find-entites"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { LovelaceCard, LovelaceCardEditor } from "../types"; import { ThermostatCardConfig } from "./types"; @@ -96,13 +96,9 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index 23155a918a..d249542f7c 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -28,7 +28,7 @@ import type { HomeAssistant, WeatherEntity } from "../../../types"; import { actionHandler } from "../common/directives/action-handler-directive"; import { findEntities } from "../common/find-entites"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import type { LovelaceCard, LovelaceCardEditor } from "../types"; import type { WeatherForecastCardConfig } from "./types"; import { installResizeObserver } from "../common/install-resize-observer"; @@ -137,13 +137,9 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/common/generate-lovelace-config.ts b/src/panels/lovelace/common/generate-lovelace-config.ts index 2e80710fcb..8941ed45d2 100644 --- a/src/panels/lovelace/common/generate-lovelace-config.ts +++ b/src/panels/lovelace/common/generate-lovelace-config.ts @@ -2,6 +2,7 @@ import { HassConfig, HassEntities, HassEntity, + STATE_NOT_RUNNING, } from "home-assistant-js-websocket"; import { computeDomain } from "../../../common/entity/compute_domain"; import { computeObjectId } from "../../../common/entity/compute_object_id"; @@ -468,6 +469,28 @@ export const generateLovelaceConfigFromHass = async ( hass: HomeAssistant, localize?: LocalizeFunc ): Promise => { + if (hass.config.state === STATE_NOT_RUNNING) { + return { + title: hass.config.location_name, + views: [ + { + cards: [{ type: "starting" }], + }, + ], + }; + } + + if (hass.config.safe_mode) { + return { + title: hass.config.location_name, + views: [ + { + cards: [{ type: "safe-mode" }], + }, + ], + }; + } + // We want to keep the registry subscriptions alive after generating the UI // so that we don't serve up stale data after changing areas. if (!subscribedRegistries) { diff --git a/src/panels/lovelace/common/has-changed.ts b/src/panels/lovelace/common/has-changed.ts index b46962bb5f..49eb8df4c7 100644 --- a/src/panels/lovelace/common/has-changed.ts +++ b/src/panels/lovelace/common/has-changed.ts @@ -17,14 +17,15 @@ export function hasConfigOrEntityChanged( if ( oldHass.themes !== element.hass!.themes || - oldHass.language !== element.hass!.language + oldHass.language !== element.hass!.language || + oldHass.localize !== element.hass.localize || + oldHass.config.state !== element.hass.config.state ) { return true; } return ( oldHass.states[element._config!.entity] !== - element.hass!.states[element._config!.entity] || - oldHass.localize !== element.hass.localize + element.hass!.states[element._config!.entity] ); } diff --git a/src/panels/lovelace/components/hui-generic-entity-row.ts b/src/panels/lovelace/components/hui-generic-entity-row.ts index 886c478a68..ab2a3a8115 100644 --- a/src/panels/lovelace/components/hui-generic-entity-row.ts +++ b/src/panels/lovelace/components/hui-generic-entity-row.ts @@ -23,7 +23,7 @@ import { EntitiesCardEntityConfig } from "../cards/types"; import { actionHandler } from "../common/directives/action-handler-directive"; import { handleAction } from "../common/handle-action"; import { hasAction } from "../common/has-action"; -import "./hui-warning"; +import { createEntityNotFoundWarning } from "./hui-warning"; class HuiGenericEntityRow extends LitElement { @property() public hass?: HomeAssistant; @@ -42,13 +42,9 @@ class HuiGenericEntityRow extends LitElement { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this.config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this.config.entity)} + `; } diff --git a/src/panels/lovelace/components/hui-warning-element.ts b/src/panels/lovelace/components/hui-warning-element.ts index e41c4fb503..bd3b1ad45e 100644 --- a/src/panels/lovelace/components/hui-warning-element.ts +++ b/src/panels/lovelace/components/hui-warning-element.ts @@ -14,7 +14,7 @@ export class HuiWarningElement extends LitElement { @property() public label?: string; protected render(): TemplateResult { - return html` `; + return html` `; } static get styles(): CSSResult { diff --git a/src/panels/lovelace/components/hui-warning.ts b/src/panels/lovelace/components/hui-warning.ts index fc903156d5..5dac061e58 100644 --- a/src/panels/lovelace/components/hui-warning.ts +++ b/src/panels/lovelace/components/hui-warning.ts @@ -6,6 +6,21 @@ import { LitElement, TemplateResult, } from "lit-element"; +import { HomeAssistant } from "../../../types"; +import { STATE_NOT_RUNNING } from "home-assistant-js-websocket"; + +export const createEntityNotFoundWarning = ( + hass: HomeAssistant, + entityId: string +) => { + return hass.config.state !== STATE_NOT_RUNNING + ? hass.localize( + "ui.panel.lovelace.warning.entity_not_found", + "entity", + entityId + ) + : hass.localize("ui.panel.lovelace.warning.starting"); +}; @customElement("hui-warning") export class HuiWarning extends LitElement { diff --git a/src/panels/lovelace/create-element/create-card-element.ts b/src/panels/lovelace/create-element/create-card-element.ts index 48a51b8782..cb5748eecf 100644 --- a/src/panels/lovelace/create-element/create-card-element.ts +++ b/src/panels/lovelace/create-element/create-card-element.ts @@ -35,6 +35,7 @@ const LAZY_LOAD_TYPES = { "alarm-panel": () => import("../cards/hui-alarm-panel-card"), error: () => import("../cards/hui-error-card"), "empty-state": () => import("../cards/hui-empty-state-card"), + starting: () => import("../cards/hui-starting-card"), "entity-filter": () => import("../cards/hui-entity-filter-card"), "media-control": () => import("../cards/hui-media-control-card"), "picture-elements": () => import("../cards/hui-picture-elements-card"), diff --git a/src/panels/lovelace/elements/hui-state-badge-element.ts b/src/panels/lovelace/elements/hui-state-badge-element.ts index a07334619c..221d9f2249 100644 --- a/src/panels/lovelace/elements/hui-state-badge-element.ts +++ b/src/panels/lovelace/elements/hui-state-badge-element.ts @@ -17,6 +17,7 @@ import { hasAction } from "../common/has-action"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-warning-element"; import { LovelaceElement, StateBadgeElementConfig } from "./types"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; @customElement("hui-state-badge-element") export class HuiStateBadgeElement extends LitElement @@ -47,11 +48,7 @@ export class HuiStateBadgeElement extends LitElement if (!stateObj) { return html` `; } diff --git a/src/panels/lovelace/elements/hui-state-icon-element.ts b/src/panels/lovelace/elements/hui-state-icon-element.ts index 73497579e8..9d24fbeda2 100644 --- a/src/panels/lovelace/elements/hui-state-icon-element.ts +++ b/src/panels/lovelace/elements/hui-state-icon-element.ts @@ -19,6 +19,7 @@ import { hasAction } from "../common/has-action"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-warning-element"; import { LovelaceElement, StateIconElementConfig } from "./types"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; @customElement("hui-state-icon-element") export class HuiStateIconElement extends LitElement implements LovelaceElement { @@ -48,11 +49,7 @@ export class HuiStateIconElement extends LitElement implements LovelaceElement { if (!stateObj) { return html` `; } diff --git a/src/panels/lovelace/elements/hui-state-label-element.ts b/src/panels/lovelace/elements/hui-state-label-element.ts index a43cc7f9ff..32132dcf99 100644 --- a/src/panels/lovelace/elements/hui-state-label-element.ts +++ b/src/panels/lovelace/elements/hui-state-label-element.ts @@ -19,6 +19,7 @@ import { hasAction } from "../common/has-action"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-warning-element"; import { LovelaceElement, StateLabelElementConfig } from "./types"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; @customElement("hui-state-label-element") class HuiStateLabelElement extends LitElement implements LovelaceElement { @@ -48,11 +49,7 @@ class HuiStateLabelElement extends LitElement implements LovelaceElement { if (!stateObj) { return html` `; } diff --git a/src/panels/lovelace/entity-rows/hui-climate-entity-row.ts b/src/panels/lovelace/entity-rows/hui-climate-entity-row.ts index 4c36a5723f..2343b2cc51 100644 --- a/src/panels/lovelace/entity-rows/hui-climate-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-climate-entity-row.ts @@ -12,7 +12,7 @@ import "../../../components/ha-climate-state"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { EntityConfig, LovelaceRow } from "./types"; @customElement("hui-climate-entity-row") @@ -42,13 +42,9 @@ class HuiClimateEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/entity-rows/hui-cover-entity-row.ts b/src/panels/lovelace/entity-rows/hui-cover-entity-row.ts index ee48aa9f10..d257601360 100644 --- a/src/panels/lovelace/entity-rows/hui-cover-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-cover-entity-row.ts @@ -14,7 +14,7 @@ import { HomeAssistant } from "../../../types"; import { isTiltOnly } from "../../../util/cover-model"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { EntityConfig, LovelaceRow } from "./types"; @customElement("hui-cover-entity-row") @@ -43,13 +43,9 @@ class HuiCoverEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/entity-rows/hui-group-entity-row.ts b/src/panels/lovelace/entity-rows/hui-group-entity-row.ts index d34420252b..20d57c97d0 100644 --- a/src/panels/lovelace/entity-rows/hui-group-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-group-entity-row.ts @@ -12,7 +12,7 @@ import "../../../components/entity/ha-entity-toggle"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { EntityConfig, LovelaceRow } from "./types"; @customElement("hui-group-entity-row") @@ -41,13 +41,9 @@ class HuiGroupEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } 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 c19ca31356..01202c5d24 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 @@ -16,6 +16,7 @@ import type { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; import type { EntityConfig, LovelaceRow } from "./types"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; @customElement("hui-input-datetime-entity-row") class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow { @@ -43,13 +44,9 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts index ab7e839980..4ea8cb338b 100644 --- a/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts @@ -16,8 +16,8 @@ import { setValue } from "../../../data/input_text"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; import { EntityConfig, LovelaceRow } from "./types"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; @customElement("hui-input-number-entity-row") class HuiInputNumberEntityRow extends LitElement implements LovelaceRow { @@ -63,13 +63,9 @@ class HuiInputNumberEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts index dbcbdd2147..1c686028c1 100644 --- a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts @@ -28,7 +28,7 @@ import { actionHandler } from "../common/directives/action-handler-directive"; import { handleAction } from "../common/handle-action"; import { hasAction } from "../common/has-action"; import { hasConfigOrEntityChanged } from "../common/has-changed"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { LovelaceRow } from "./types"; @customElement("hui-input-select-entity-row") @@ -60,13 +60,9 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } 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 d2fcf6a71e..dc9e69366d 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 @@ -12,7 +12,7 @@ import { setValue } from "../../../data/input_text"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { EntityConfig, LovelaceRow } from "./types"; @customElement("hui-input-text-entity-row") @@ -41,13 +41,9 @@ class HuiInputTextEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/entity-rows/hui-lock-entity-row.ts b/src/panels/lovelace/entity-rows/hui-lock-entity-row.ts index d37018cd71..cb9c74d262 100644 --- a/src/panels/lovelace/entity-rows/hui-lock-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-lock-entity-row.ts @@ -13,7 +13,7 @@ import { UNAVAILABLE_STATES } from "../../../data/entity"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { EntityConfig, LovelaceRow } from "./types"; @customElement("hui-lock-entity-row") @@ -42,13 +42,9 @@ class HuiLockEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts index 16bed1f07b..76ebd5366c 100644 --- a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts @@ -30,7 +30,7 @@ import { import type { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import type { EntityConfig, LovelaceRow } from "./types"; import { installResizeObserver } from "../common/install-resize-observer"; import { computeStateDisplay } from "../../../common/entity/compute_state_display"; @@ -82,13 +82,9 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } 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 87e16c12b7..0da4b598aa 100644 --- a/src/panels/lovelace/entity-rows/hui-scene-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-scene-entity-row.ts @@ -15,7 +15,7 @@ import { activateScene } from "../../../data/scene"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { ActionRowConfig, LovelaceRow } from "./types"; @customElement("hui-scene-entity-row") @@ -44,13 +44,9 @@ class HuiSceneEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } 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 01e8a5bddb..1105b6216e 100644 --- a/src/panels/lovelace/entity-rows/hui-script-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-script-entity-row.ts @@ -14,7 +14,7 @@ import { UNAVAILABLE_STATES } from "../../../data/entity"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { ActionRowConfig, LovelaceRow } from "./types"; @customElement("hui-script-entity-row") @@ -43,13 +43,9 @@ class HuiScriptEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/entity-rows/hui-sensor-entity-row.ts b/src/panels/lovelace/entity-rows/hui-sensor-entity-row.ts index e59f9028e8..f479c25695 100644 --- a/src/panels/lovelace/entity-rows/hui-sensor-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-sensor-entity-row.ts @@ -14,7 +14,7 @@ import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; import "../components/hui-timestamp-display"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { LovelaceRow } from "./types"; import { EntitiesCardEntityConfig } from "../cards/types"; import { actionHandler } from "../common/directives/action-handler-directive"; @@ -52,13 +52,9 @@ class HuiSensorEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/entity-rows/hui-text-entity-row.ts b/src/panels/lovelace/entity-rows/hui-text-entity-row.ts index bd423896ce..de9eeb0fce 100644 --- a/src/panels/lovelace/entity-rows/hui-text-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-text-entity-row.ts @@ -12,7 +12,7 @@ import { computeStateDisplay } from "../../../common/entity/compute_state_displa import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { LovelaceRow } from "./types"; import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const"; import { computeDomain } from "../../../common/entity/compute_domain"; @@ -49,13 +49,9 @@ class HuiTextEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts index c2b167119b..b99596eddf 100644 --- a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts @@ -12,7 +12,7 @@ import { timerTimeRemaining } from "../../../common/entity/timer_time_remaining" import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { EntityConfig } from "./types"; @customElement("hui-timer-entity-row") @@ -56,13 +56,9 @@ class HuiTimerEntityRow extends LitElement { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } 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 94efa0b92a..661281fe9f 100644 --- a/src/panels/lovelace/entity-rows/hui-toggle-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-toggle-entity-row.ts @@ -12,7 +12,7 @@ import { UNAVAILABLE_STATES } from "../../../data/entity"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import { EntityConfig, LovelaceRow } from "./types"; @customElement("hui-toggle-entity-row") @@ -41,13 +41,9 @@ class HuiToggleEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/entity-rows/hui-weather-entity-row.ts b/src/panels/lovelace/entity-rows/hui-weather-entity-row.ts index 9f3884758e..7af231937c 100644 --- a/src/panels/lovelace/entity-rows/hui-weather-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-weather-entity-row.ts @@ -24,7 +24,7 @@ import type { HomeAssistant, WeatherEntity } from "../../../types"; import type { EntitiesCardEntityConfig } from "../cards/types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; import type { LovelaceRow } from "./types"; import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const"; import { computeDomain } from "../../../common/entity/compute_domain"; @@ -62,13 +62,9 @@ class HuiWeatherEntityRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/panels/lovelace/ha-panel-lovelace.ts b/src/panels/lovelace/ha-panel-lovelace.ts index 0e802519ce..7cac078da7 100644 --- a/src/panels/lovelace/ha-panel-lovelace.ts +++ b/src/panels/lovelace/ha-panel-lovelace.ts @@ -26,6 +26,7 @@ import { loadLovelaceResources } from "./common/load-resources"; import { showSaveDialog } from "./editor/show-save-config-dialog"; import "./hui-root"; import { Lovelace } from "./types"; +import { STATE_NOT_RUNNING } from "home-assistant-js-websocket"; (window as any).loadCardHelpers = () => import("./custom-card-helpers"); @@ -169,7 +170,13 @@ class LovelacePanel extends LitElement { } // reload lovelace on reconnect so we are sure we have the latest config window.addEventListener("connection-status", (ev) => { - if (ev.detail === "connected") { + if ( + ev.detail === "connected" && + !( + this.lovelace?.mode === "generated" && + this.hass!.config.state === STATE_NOT_RUNNING + ) + ) { this._fetchConfig(false); } }); diff --git a/src/panels/lovelace/special-rows/hui-attribute-row.ts b/src/panels/lovelace/special-rows/hui-attribute-row.ts index 9a5db8a85f..29d611a3cd 100644 --- a/src/panels/lovelace/special-rows/hui-attribute-row.ts +++ b/src/panels/lovelace/special-rows/hui-attribute-row.ts @@ -11,8 +11,8 @@ import { import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; -import "../components/hui-warning"; import { AttributeRowConfig, LovelaceRow } from "../entity-rows/types"; +import { createEntityNotFoundWarning } from "../components/hui-warning"; @customElement("hui-attribute-row") class HuiAttributeRow extends LitElement implements LovelaceRow { @@ -47,13 +47,9 @@ class HuiAttributeRow extends LitElement implements LovelaceRow { if (!stateObj) { return html` - ${this.hass.localize( - "ui.panel.lovelace.warning.entity_not_found", - "entity", - this._config.entity - )} + + ${createEntityNotFoundWarning(this.hass, this._config.entity)} + `; } diff --git a/src/state/connection-mixin.ts b/src/state/connection-mixin.ts index 045c758806..43496426a8 100644 --- a/src/state/connection-mixin.ts +++ b/src/state/connection-mixin.ts @@ -6,6 +6,7 @@ import { subscribeConfig, subscribeEntities, subscribeServices, + HassConfig, } from "home-assistant-js-websocket"; import { fireEvent } from "../common/dom/fire_event"; import { broadcastConnectionStatus } from "../data/connection-status"; @@ -156,8 +157,15 @@ export const connectionMixin = >( protected hassReconnected() { super.hassReconnected(); + this._updateHass({ connected: true }); broadcastConnectionStatus("connected"); + + // on reconnect always fetch config as we might miss an update while we were disconnected + // @ts-ignore + this.hass!.callWS({ type: "get_config" }).then((config: HassConfig) => { + this._updateHass({ config }); + }); } protected hassDisconnected() { diff --git a/src/state/disconnect-toast-mixin.ts b/src/state/disconnect-toast-mixin.ts index 006cdad269..376bbcfbcb 100644 --- a/src/state/disconnect-toast-mixin.ts +++ b/src/state/disconnect-toast-mixin.ts @@ -1,6 +1,11 @@ import { Constructor } from "../types"; import { showToast } from "../util/toast"; import { HassBaseEl } from "./hass-base-mixin"; +import { + STATE_NOT_RUNNING, + STATE_STARTING, + STATE_RUNNING, +} from "home-assistant-js-websocket"; export default >(superClass: T) => class extends superClass { @@ -12,6 +17,34 @@ export default >(superClass: T) => ); } + updated(changedProperties) { + super.updated(changedProperties); + const oldHass = changedProperties.get("hass"); + if ( + !changedProperties.has("hass") || + !oldHass?.config || + oldHass.config.state === this.hass!.config.state + ) { + return; + } + if (this.hass!.config.state === STATE_NOT_RUNNING) { + showToast(this, { + message: this.hass!.localize("ui.notification_toast.starting"), + duration: 0, + dismissable: false, + }); + } else if ( + oldHass.config.state === STATE_NOT_RUNNING && + (this.hass!.config.state === STATE_STARTING || + this.hass!.config.state === STATE_RUNNING) + ) { + showToast(this, { + message: this.hass!.localize("ui.notification_toast.started"), + duration: 5000, + }); + } + } + protected hassReconnected() { super.hassReconnected(); diff --git a/src/translations/en.json b/src/translations/en.json index d297cc2d3e..81b91024a2 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -498,6 +498,8 @@ "notification_toast": { "service_call_failed": "Failed to call service {service}.", "connection_lost": "Connection lost. Reconnecting…", + "started": "Home Assistant has started!", + "starting": "Home Assistant is starting, not everything will be available until it is finished.", "triggered": "Triggered {name}" }, "sidebar": { @@ -1644,6 +1646,10 @@ "safe-mode": { "header": "Safe Mode Activated", "description": "Home Assistant ran into trouble while loading your configuration and is now running in safe mode. Take a look at the error log to see what went wrong." + }, + "starting": { + "header": "Home Assistant is starting...", + "description": "Home Assistant is starting up, please wait." } }, "unused_entities": { @@ -1936,7 +1942,8 @@ "attribute_not_found": "Attribute {attribute} not available in: {entity}", "entity_not_found": "Entity not available: {entity}", "entity_non_numeric": "Entity is non-numeric: {entity}", - "entity_unavailable": "{entity} is currently unavailable" + "entity_unavailable": "{entity} is currently unavailable", + "starting": "Home Assistant is starting, not everything may be available yet" }, "changed_toast": { "message": "The Lovelace UI configuration for this dashboard was updated, refresh to see changes?", diff --git a/yarn.lock b/yarn.lock index 5c2c066356..3354f10e19 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6613,10 +6613,10 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -home-assistant-js-websocket@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/home-assistant-js-websocket/-/home-assistant-js-websocket-5.1.2.tgz#418c027ccb0f0817004931fce4cf5c64241d16ed" - integrity sha512-tV6bLgvLHBev2tb0h6tujsLuLKZqO2qTrO6jTDx8oSDA5vo9zOEcc6QsuhC/AaTdtniT6l4UuTwsps9Wlk6nJw== +home-assistant-js-websocket@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/home-assistant-js-websocket/-/home-assistant-js-websocket-5.2.1.tgz#88c06738416e041dfd805f2543722458d9c3a391" + integrity sha512-azPiR+KABxaow1sMS70+Jk12KOaKSJY9KSKSGljkAArJmbWum3PEMNXXaG+XJnYmNuDnyzLAwi3/e1cwvVqocA== homedir-polyfill@^1.0.1: version "1.0.3"