Improve broken cards on dashboards (#25557)

This commit is contained in:
Jan-Philipp Benecke 2025-05-26 10:45:22 +02:00 committed by GitHub
parent 549451eccb
commit 28fe60f02b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
56 changed files with 170 additions and 139 deletions

View File

@ -41,6 +41,7 @@ import type {
} from "../../types"; } from "../../types";
import { showCalendarEventDetailDialog } from "./show-dialog-calendar-event-detail"; import { showCalendarEventDetailDialog } from "./show-dialog-calendar-event-detail";
import { showCalendarEventEditDialog } from "./show-dialog-calendar-event-editor"; import { showCalendarEventEditDialog } from "./show-dialog-calendar-event-editor";
import "../lovelace/components/hui-warning";
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
@ -126,11 +127,8 @@ export class HAFullCalendar extends LitElement {
${this.calendar ${this.calendar
? html` ? html`
${this.error ${this.error
? html`<ha-alert ? html`<hui-warning .hass=${this.hass} severity="warning"
alert-type="error" >${this.error}</hui-warning
dismissable
@alert-dismissed-clicked=${this._clearError}
>${this.error}</ha-alert
>` >`
: ""} : ""}
<div class="header"> <div class="header">
@ -420,10 +418,6 @@ export class HAFullCalendar extends LitElement {
); );
}); });
private _clearError() {
this.error = undefined;
}
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return [ return [
haStyle, haStyle,
@ -510,11 +504,6 @@ export class HAFullCalendar extends LitElement {
z-index: 1; z-index: 1;
} }
ha-alert {
display: block;
margin: 4px 0;
}
#calendar { #calendar {
flex-grow: 1; flex-grow: 1;
background-color: var( background-color: var(

View File

@ -86,7 +86,7 @@ class HuiEnergyCarbonGaugeCard
const co2State = this.hass.states[this._data.co2SignalEntity]; const co2State = this.hass.states[this._data.co2SignalEntity];
if (!co2State) { if (!co2State) {
return html`<hui-warning> return html`<hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._data.co2SignalEntity)} ${createEntityNotFoundWarning(this.hass, this._data.co2SignalEntity)}
</hui-warning>`; </hui-warning>`;
} }

View File

@ -220,7 +220,7 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -363,7 +363,7 @@ export class HuiAreaCard
if (area === null) { if (area === null) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${this.hass.localize("ui.card.area.area_not_found")} ${this.hass.localize("ui.card.area.area_not_found")}
</hui-warning> </hui-warning>
`; `;

View File

@ -179,7 +179,7 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
if (this._config.entity && !stateObj) { if (this._config.entity && !stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -4,7 +4,6 @@ import { customElement, property, state } from "lit/decorators";
import { getColorByIndex } from "../../../common/color/colors"; import { getColorByIndex } from "../../../common/color/colors";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import type { HASSDomEvent } from "../../../common/dom/fire_event"; import type { HASSDomEvent } from "../../../common/dom/fire_event";
import { computeStateName } from "../../../common/entity/compute_state_name";
import { debounce } from "../../../common/util/debounce"; import { debounce } from "../../../common/util/debounce";
import "../../../components/ha-card"; import "../../../components/ha-card";
import type { Calendar, CalendarEvent } from "../../../data/calendar"; import type { Calendar, CalendarEvent } from "../../../data/calendar";
@ -176,17 +175,9 @@ export class HuiCalendarCard extends LitElement implements LovelaceCard {
this._events = result.events; this._events = result.events;
if (result.errors.length > 0) { if (result.errors.length > 0) {
const nameList = result.errors
.map((error_entity_id) =>
this.hass!.states[error_entity_id]
? computeStateName(this.hass!.states[error_entity_id])
: error_entity_id
)
.join(", ");
this._error = `${this.hass!.localize( this._error = `${this.hass!.localize(
"ui.components.calendar.event_retrieval_error" "ui.components.calendar.event_retrieval_error"
)} ${nameList}`; )}`;
} }
} }

View File

@ -13,7 +13,6 @@ import {
checkConditionsMet, checkConditionsMet,
} from "../common/validate-condition"; } from "../common/validate-condition";
import { createCardElement } from "../create-element/create-card-element"; import { createCardElement } from "../create-element/create-card-element";
import { createErrorCardConfig } from "../create-element/create-element-base";
import type { LovelaceCard, LovelaceGridOptions } from "../types"; import type { LovelaceCard, LovelaceGridOptions } from "../types";
declare global { declare global {
@ -191,7 +190,9 @@ export class HuiCard extends ReactiveElement {
this._element.hass = this.hass; this._element.hass = this.hass;
} }
} catch (e: any) { } catch (e: any) {
this._loadElement(createErrorCardConfig(e.message, null)); // eslint-disable-next-line no-console
console.error(this.config?.type, e);
this._loadElement({ type: "error" });
} }
} }
if (changedProps.has("preview")) { if (changedProps.has("preview")) {
@ -200,7 +201,9 @@ export class HuiCard extends ReactiveElement {
// For backwards compatibility // For backwards compatibility
(this._element as any).editMode = this.preview; (this._element as any).editMode = this.preview;
} catch (e: any) { } catch (e: any) {
this._loadElement(createErrorCardConfig(e.message, null)); // eslint-disable-next-line no-console
console.error(this.config?.type, e);
this._loadElement({ type: "error" });
} }
} }
if (changedProps.has("layout")) { if (changedProps.has("layout")) {
@ -209,7 +212,9 @@ export class HuiCard extends ReactiveElement {
// For backwards compatibility // For backwards compatibility
(this._element as any).isPanel = this.layout === "panel"; (this._element as any).isPanel = this.layout === "panel";
} catch (e: any) { } catch (e: any) {
this._loadElement(createErrorCardConfig(e.message, null)); // eslint-disable-next-line no-console
console.error(this.config?.type, e);
this._loadElement({ type: "error" });
} }
} }
} }

View File

@ -114,7 +114,7 @@ export class HuiEntityCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -1,52 +1,106 @@
import { dump } from "js-yaml";
import { css, html, LitElement, nothing } from "lit"; import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import "../../../components/ha-alert"; import { mdiAlertCircleOutline, mdiAlertOutline } from "@mdi/js";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import type { LovelaceCard } from "../types"; import type { LovelaceCard, LovelaceGridOptions } from "../types";
import type { ErrorCardConfig } from "./types"; import type { ErrorCardConfig } from "./types";
import "../../../components/ha-card";
import "../../../components/ha-svg-icon";
const ERROR_ICONS = {
warning: mdiAlertOutline,
error: mdiAlertCircleOutline,
};
@customElement("hui-error-card") @customElement("hui-error-card")
export class HuiErrorCard extends LitElement implements LovelaceCard { export class HuiErrorCard extends LitElement implements LovelaceCard {
public hass?: HomeAssistant; @property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public preview = false; @property({ attribute: false }) public preview = false;
@property({ attribute: "severity" }) public severity: "warning" | "error" =
"error";
@state() private _config?: ErrorCardConfig; @state() private _config?: ErrorCardConfig;
public getCardSize(): number { public getCardSize(): number {
return 4; return 1;
}
public getGridOptions(): LovelaceGridOptions {
return {
columns: 6,
rows: 1,
min_rows: 1,
min_columns: 6,
};
} }
public setConfig(config: ErrorCardConfig): void { public setConfig(config: ErrorCardConfig): void {
this._config = config; this._config = config;
this.severity = config.severity || "error";
} }
protected render() { protected render() {
if (!this._config) { const error =
return nothing; this._config?.error ||
} this.hass?.localize("ui.errors.config.configuration_error");
const showTitle = this.hass === undefined || this.hass?.user?.is_admin;
let dumped: string | undefined; return html`
<ha-card class="${this.severity} ${showTitle ? "" : "no-title"}">
if (this._config.origConfig) { <div class="icon">
try { <slot name="icon">
dumped = dump(this._config.origConfig); <ha-svg-icon .path=${ERROR_ICONS[this.severity]}></ha-svg-icon>
} catch (_err: any) { </slot>
dumped = `[Error dumping ${this._config.origConfig}]`; </div>
} ${showTitle
} ? html`<div class="title"><slot>${error}</slot></div>`
: nothing}
return html`<ha-alert alert-type="error" .title=${this._config.error}> </ha-card>
${dumped ? html`<pre>${dumped}</pre>` : ""} `;
</ha-alert>`;
} }
static styles = css` static styles = css`
pre { ha-card {
font-family: var(--ha-font-family-code); height: 100%;
white-space: break-spaces; border-width: 0;
user-select: text; display: flex;
align-items: center;
column-gap: 16px;
padding: 16px;
}
ha-card::after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0.12;
pointer-events: none;
content: "";
border-radius: var(--ha-card-border-radius, 12px);
}
.no-title {
justify-content: center;
}
.title {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-weight: var(--ha-font-weight-bold);
}
ha-card.warning > .icon {
color: var(--warning-color);
}
ha-card.warning::after {
background-color: var(--warning-color);
}
ha-card.error > .icon {
color: var(--error-color);
}
ha-card.error::after {
background-color: var(--error-color);
} }
`; `;
} }

View File

@ -90,7 +90,7 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -121,7 +121,7 @@ export class HuiHumidifierCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -82,7 +82,7 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -174,7 +174,7 @@ export class HuiLogbookCard extends LitElement implements LovelaceCard {
if (!isComponentLoaded(this.hass, "logbook")) { if (!isComponentLoaded(this.hass, "logbook")) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${this.hass.localize("ui.components.logbook.not_loaded", { ${this.hass.localize("ui.components.logbook.not_loaded", {
platform: "logbook", platform: "logbook",
})}</hui-warning })}</hui-warning

View File

@ -145,7 +145,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -100,7 +100,7 @@ export class HuiPictureCard extends LitElement implements LovelaceCard {
if (this._config.image_entity) { if (this._config.image_entity) {
stateObj = this.hass.states[this._config.image_entity]; stateObj = this.hass.states[this._config.image_entity];
if (!stateObj) { if (!stateObj) {
return html`<hui-warning> return html`<hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.image_entity)} ${createEntityNotFoundWarning(this.hass, this._config.image_entity)}
</hui-warning>`; </hui-warning>`;
} }

View File

@ -119,7 +119,7 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -104,7 +104,7 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -113,7 +113,7 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -1,4 +1,3 @@
import { mdiExclamationThick, mdiHelp } from "@mdi/js";
import type { HassEntity } from "home-assistant-js-websocket"; import type { HassEntity } from "home-assistant-js-websocket";
import { LitElement, css, html, nothing } from "lit"; import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
@ -37,6 +36,7 @@ import type {
} from "../types"; } from "../types";
import { renderTileBadge } from "./tile/badges/tile-badge"; import { renderTileBadge } from "./tile/badges/tile-badge";
import type { TileCardConfig } from "./types"; import type { TileCardConfig } from "./types";
import { createEntityNotFoundWarning } from "../components/hui-warning";
export const getEntityDefaultTileIconAction = (entityId: string) => { export const getEntityDefaultTileIconAction = (entityId: string) => {
const domain = computeDomain(entityId); const domain = computeDomain(entityId);
@ -249,20 +249,9 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<ha-card> <hui-warning .hass=${this.hass}>
<div class="content ${classMap(contentClasses)}"> ${createEntityNotFoundWarning(this.hass, this._config.entity)}
<ha-tile-icon> </hui-warning>
<ha-svg-icon slot="icon" .path=${mdiHelp}></ha-svg-icon>
<ha-tile-badge class="not-found">
<ha-svg-icon .path=${mdiExclamationThick}></ha-svg-icon>
</ha-tile-badge>
</ha-tile-icon>
<ha-tile-info
.primary=${entityId}
secondary=${this.hass.localize("ui.card.tile.not_found")}
></ha-tile-info>
</div>
</ha-card>
`; `;
} }

View File

@ -241,7 +241,7 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._entityId)} ${createEntityNotFoundWarning(this.hass, this._entityId)}
</hui-warning> </hui-warning>
`; `;

View File

@ -210,7 +210,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -215,8 +215,9 @@ export interface EntityFilterCardConfig extends LovelaceCardConfig {
} }
export interface ErrorCardConfig extends LovelaceCardConfig { export interface ErrorCardConfig extends LovelaceCardConfig {
error: string; error?: string;
origConfig: LovelaceCardConfig; origConfig?: LovelaceCardConfig;
severity?: "warning" | "error";
} }
export interface SeverityConfig { export interface SeverityConfig {

View File

@ -46,7 +46,7 @@ export class HuiGenericEntityRow extends LitElement {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this.config.entity)} ${createEntityNotFoundWarning(this.hass, this.config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -1,24 +1,28 @@
import { STATE_NOT_RUNNING } from "home-assistant-js-websocket"; import { STATE_NOT_RUNNING } from "home-assistant-js-websocket";
import type { TemplateResult } from "lit"; import type { TemplateResult } from "lit";
import { html, LitElement } from "lit"; import { html, LitElement } from "lit";
import { customElement } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import "../../../components/ha-alert"; import "../../../components/ha-alert";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import "../cards/hui-error-card";
export const createEntityNotFoundWarning = ( export const createEntityNotFoundWarning = (
hass: HomeAssistant, hass: HomeAssistant,
entityId: string // left for backwards compatibility for custom cards
_entityId: string
) => ) =>
hass.config.state !== STATE_NOT_RUNNING hass.config.state !== STATE_NOT_RUNNING
? hass.localize("ui.panel.lovelace.warning.entity_not_found", { ? hass.localize("ui.card.common.entity_not_found")
entity: entityId || "[empty]",
})
: hass.localize("ui.panel.lovelace.warning.starting"); : hass.localize("ui.panel.lovelace.warning.starting");
@customElement("hui-warning") @customElement("hui-warning")
export class HuiWarning extends LitElement { export class HuiWarning extends LitElement {
@property({ attribute: false }) public hass?: HomeAssistant;
protected render(): TemplateResult { protected render(): TemplateResult {
return html`<ha-alert alert-type="warning"><slot></slot></ha-alert> `; return html`<hui-error-card .hass=${this.hass} severity="warning"
><slot></slot
></hui-error-card>`;
} }
} }

View File

@ -16,7 +16,10 @@ import type { ErrorCardConfig } from "../cards/types";
import type { LovelaceElement, LovelaceElementConfig } from "../elements/types"; import type { LovelaceElement, LovelaceElementConfig } from "../elements/types";
import type { LovelaceRow, LovelaceRowConfig } from "../entity-rows/types"; import type { LovelaceRow, LovelaceRowConfig } from "../entity-rows/types";
import type { LovelaceHeaderFooterConfig } from "../header-footer/types"; import type { LovelaceHeaderFooterConfig } from "../header-footer/types";
import type { LovelaceHeadingBadgeConfig } from "../heading-badges/types"; import type {
ErrorBadgeConfig as ErrorHeadingBadgeConfig,
LovelaceHeadingBadgeConfig,
} from "../heading-badges/types";
import type { import type {
LovelaceBadge, LovelaceBadge,
LovelaceBadgeConstructor, LovelaceBadgeConstructor,
@ -31,6 +34,7 @@ import type {
LovelaceHeadingBadgeConstructor, LovelaceHeadingBadgeConstructor,
LovelaceRowConstructor, LovelaceRowConstructor,
} from "../types"; } from "../types";
import type { ErrorBadgeConfig } from "../badges/types";
const TIMEOUT = 2000; const TIMEOUT = 2000;
@ -96,7 +100,7 @@ export const createErrorCardElement = (config: ErrorCardConfig) => {
return el; return el;
}; };
export const createErrorBadgeElement = (config: ErrorCardConfig) => { export const createErrorBadgeElement = (config: ErrorBadgeConfig) => {
const el = document.createElement("hui-error-badge"); const el = document.createElement("hui-error-badge");
if (customElements.get("hui-error-badge")) { if (customElements.get("hui-error-badge")) {
el.setConfig(config); el.setConfig(config);
@ -110,7 +114,9 @@ export const createErrorBadgeElement = (config: ErrorCardConfig) => {
return el; return el;
}; };
export const createErrorHeadingBadgeElement = (config: ErrorCardConfig) => { export const createErrorHeadingBadgeElement = (
config: ErrorHeadingBadgeConfig
) => {
const el = document.createElement("hui-error-heading-badge"); const el = document.createElement("hui-error-heading-badge");
if (customElements.get("hui-error-heading-badge")) { if (customElements.get("hui-error-heading-badge")) {
el.setConfig(config); el.setConfig(config);
@ -124,12 +130,6 @@ export const createErrorHeadingBadgeElement = (config: ErrorCardConfig) => {
return el; return el;
}; };
export const createErrorCardConfig = (error, origConfig) => ({
type: "error",
error,
origConfig,
});
export const createErrorBadgeConfig = (error, origConfig) => ({ export const createErrorBadgeConfig = (error, origConfig) => ({
type: "error", type: "error",
error, error,
@ -167,7 +167,7 @@ const _createErrorElement = <T extends keyof CreateElementConfigTypes>(
createErrorHeadingBadgeConfig(error, config) createErrorHeadingBadgeConfig(error, config)
); );
} }
return createErrorCardElement(createErrorCardConfig(error, config)); return createErrorCardElement({ type: "error" });
}; };
const _customCreate = <T extends keyof CreateElementConfigTypes>( const _customCreate = <T extends keyof CreateElementConfigTypes>(

View File

@ -36,7 +36,7 @@ class HuiButtonEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -35,7 +35,7 @@ class HuiClimateEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -37,7 +37,7 @@ class HuiCoverEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -36,7 +36,7 @@ class HuiDateEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -39,7 +39,7 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -45,7 +45,7 @@ class HuiEventEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -49,7 +49,7 @@ class HuiGroupEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -37,7 +37,7 @@ class HuiHumidifierEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -36,7 +36,7 @@ class HuiInputButtonEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -41,7 +41,7 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -65,7 +65,7 @@ class HuiInputNumberEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -45,7 +45,7 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -37,7 +37,7 @@ class HuiInputTextEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -37,7 +37,7 @@ class HuiLockEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -92,7 +92,7 @@ class HuiMediaPlayerEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -65,7 +65,7 @@ class HuiNumberEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -38,7 +38,7 @@ class HuiSceneEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -39,7 +39,7 @@ class HuiScriptEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -45,7 +45,7 @@ class HuiSelectEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -42,7 +42,7 @@ class HuiSensorEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -34,7 +34,7 @@ class HuiSimpleEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -40,7 +40,7 @@ class HuiTextEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -37,7 +37,7 @@ class HuiTimeEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -30,7 +30,7 @@ class HuiTimerEntityRow extends LitElement {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -35,7 +35,7 @@ class HuiToggleEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -38,7 +38,7 @@ class HuiUpdateEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -35,7 +35,7 @@ class HuiValveEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -105,7 +105,7 @@ class HuiWeatherEntityRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -42,7 +42,7 @@ class HuiAttributeRow extends LitElement implements LovelaceRow {
if (!stateObj) { if (!stateObj) {
return html` return html`
<hui-warning> <hui-warning .hass=${this.hass}>
${createEntityNotFoundWarning(this.hass, this._config.entity)} ${createEntityNotFoundWarning(this.hass, this._config.entity)}
</hui-warning> </hui-warning>
`; `;

View File

@ -63,7 +63,7 @@ export class PanelView extends LitElement implements LovelaceViewElement {
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
${this.cards!.length > 1 ${this.cards!.length > 1
? html`<hui-warning> ? html`<hui-warning .hass=${this.hass}>
${this.hass!.localize( ${this.hass!.localize(
"ui.panel.lovelace.editor.view.panel_mode.warning_multiple_cards" "ui.panel.lovelace.editor.view.panel_mode.warning_multiple_cards"
)} )}

View File

@ -72,14 +72,15 @@
}, },
"badge": { "badge": {
"entity": { "entity": {
"not_found": "[%key:ui::card::tile::not_found%]" "not_found": "[%key:ui::card::common::entity_not_found%]"
} }
}, },
"card": { "card": {
"common": { "common": {
"turn_on": "Turn on", "turn_on": "Turn on",
"turn_off": "Turn off", "turn_off": "Turn off",
"toggle": "Toggle" "toggle": "Toggle",
"entity_not_found": "Entity not found"
}, },
"alarm_control_panel": { "alarm_control_panel": {
"code": "Code", "code": "Code",
@ -257,9 +258,6 @@
"finish": "finish" "finish": "finish"
} }
}, },
"tile": {
"not_found": "Entity not found"
},
"vacuum": { "vacuum": {
"actions": { "actions": {
"resume_cleaning": "Resume cleaning", "resume_cleaning": "Resume cleaning",
@ -1010,7 +1008,7 @@
"my_calendars": "My calendars", "my_calendars": "My calendars",
"create_calendar": "Create calendar", "create_calendar": "Create calendar",
"today": "Today", "today": "Today",
"event_retrieval_error": "Could not retrieve events for calendars:", "event_retrieval_error": "Could not retrieve events for calendars",
"event": { "event": {
"add": "Add event", "add": "Add event",
"delete": "Delete event", "delete": "Delete event",