From d542b52ebd658428ba0e5ebdbd1732034294f407 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 11 Jun 2025 12:04:54 +0200 Subject: [PATCH] Display full error for card preview mode (#25747) --- src/panels/lovelace/cards/hui-card.ts | 29 +++++++++++-- src/panels/lovelace/cards/hui-error-card.ts | 47 +++++++++++++-------- src/panels/lovelace/types.ts | 2 + 3 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/panels/lovelace/cards/hui-card.ts b/src/panels/lovelace/cards/hui-card.ts index dd3bcbeb30..cba0e15aea 100644 --- a/src/panels/lovelace/cards/hui-card.ts +++ b/src/panels/lovelace/cards/hui-card.ts @@ -12,7 +12,8 @@ import { attachConditionMediaQueriesListeners, checkConditionsMet, } from "../common/validate-condition"; -import { createCardElement } from "../create-element/create-card-element"; +import { tryCreateCardElement } from "../create-element/create-card-element"; +import { createErrorCardElement } from "../create-element/create-element-base"; import type { LovelaceCard, LovelaceGridOptions } from "../types"; declare global { @@ -71,10 +72,23 @@ export class HuiCard extends ReactiveElement { public getGridOptions(): LovelaceGridOptions { const elementOptions = this.getElementGridOptions(); const configOptions = this.getConfigGridOptions(); - return { + const mergedConfig = { ...elementOptions, ...configOptions, }; + + // If the element has fixed rows or columns, we use the values from the element + if (elementOptions.fixed_rows) { + mergedConfig.rows = elementOptions.rows; + delete mergedConfig.min_rows; + delete mergedConfig.max_rows; + } + if (elementOptions.fixed_columns) { + mergedConfig.columns = elementOptions.columns; + delete mergedConfig.min_columns; + delete mergedConfig.max_columns; + } + return mergedConfig; } // options provided by the element @@ -119,7 +133,15 @@ export class HuiCard extends ReactiveElement { } private _loadElement(config: LovelaceCardConfig) { - this._element = createCardElement(config); + try { + this._element = tryCreateCardElement(config); + } catch (err: unknown) { + const errorMessage = err instanceof Error ? err.message : undefined; + this._element = createErrorCardElement({ + type: "error", + message: errorMessage, + }); + } this._elementConfig = config; if (this.hass) { this._element.hass = this.hass; @@ -200,6 +222,7 @@ export class HuiCard extends ReactiveElement { this._element.preview = this.preview; // For backwards compatibility (this._element as any).editMode = this.preview; + fireEvent(this, "card-updated"); } catch (e: any) { // eslint-disable-next-line no-console console.error(this.config?.type, e); diff --git a/src/panels/lovelace/cards/hui-error-card.ts b/src/panels/lovelace/cards/hui-error-card.ts index 837f78e367..26d72284d6 100644 --- a/src/panels/lovelace/cards/hui-error-card.ts +++ b/src/panels/lovelace/cards/hui-error-card.ts @@ -1,11 +1,11 @@ +import { mdiAlertCircleOutline, mdiAlertOutline } from "@mdi/js"; import { css, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; -import { mdiAlertCircleOutline, mdiAlertOutline } from "@mdi/js"; +import "../../../components/ha-card"; +import "../../../components/ha-svg-icon"; import type { HomeAssistant } from "../../../types"; import type { LovelaceCard, LovelaceGridOptions } from "../types"; import type { ErrorCardConfig } from "./types"; -import "../../../components/ha-card"; -import "../../../components/ha-svg-icon"; const ERROR_ICONS = { warning: mdiAlertOutline, @@ -30,9 +30,10 @@ export class HuiErrorCard extends LitElement implements LovelaceCard { public getGridOptions(): LovelaceGridOptions { return { columns: 6, - rows: 1, + rows: this.preview ? "auto" : 1, min_rows: 1, min_columns: 6, + fixed_rows: this.preview, }; } @@ -45,17 +46,24 @@ export class HuiErrorCard extends LitElement implements LovelaceCard { const error = this._config?.error || this.hass?.localize("ui.errors.config.configuration_error"); - const showTitle = this.hass === undefined || this.hass?.user?.is_admin; + const showTitle = + this.hass === undefined || this.hass?.user?.is_admin || this.preview; + const showMessage = this.preview; return html` -
- - - +
+
+ + + +
+ ${showTitle + ? html`
${error}
` + : nothing}
- ${showTitle - ? html`
${error}
` + ${showMessage && this._config?.message + ? html`
${this._config.message}
` : nothing} `; @@ -65,10 +73,6 @@ export class HuiErrorCard extends LitElement implements LovelaceCard { ha-card { height: 100%; border-width: 0; - display: flex; - align-items: center; - column-gap: 16px; - padding: 16px; } ha-card::after { position: absolute; @@ -81,6 +85,15 @@ export class HuiErrorCard extends LitElement implements LovelaceCard { content: ""; border-radius: var(--ha-card-border-radius, 12px); } + .header { + display: flex; + align-items: center; + gap: 8px; + padding: 16px; + } + .message { + padding: 0 16px 16px 16px; + } .no-title { justify-content: center; } @@ -90,13 +103,13 @@ export class HuiErrorCard extends LitElement implements LovelaceCard { text-overflow: ellipsis; font-weight: var(--ha-font-weight-bold); } - ha-card.warning > .icon { + ha-card.warning .icon { color: var(--warning-color); } ha-card.warning::after { background-color: var(--warning-color); } - ha-card.error > .icon { + ha-card.error .icon { color: var(--error-color); } ha-card.error::after { diff --git a/src/panels/lovelace/types.ts b/src/panels/lovelace/types.ts index 8da041bb27..40534349bf 100644 --- a/src/panels/lovelace/types.ts +++ b/src/panels/lovelace/types.ts @@ -62,6 +62,8 @@ export interface LovelaceGridOptions { min_columns?: number; min_rows?: number; max_rows?: number; + fixed_rows?: boolean; + fixed_columns?: boolean; } export interface LovelaceCard extends HTMLElement {