Display full error for card preview mode

display_full_error_preview_mode_card
Paul Bottein 2025-06-11 11:19:50 +02:00
parent 1f8e768220
commit fefb642c0f
No known key found for this signature in database
3 changed files with 58 additions and 20 deletions

View File

@ -12,7 +12,8 @@ import {
attachConditionMediaQueriesListeners, attachConditionMediaQueriesListeners,
checkConditionsMet, checkConditionsMet,
} from "../common/validate-condition"; } 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"; import type { LovelaceCard, LovelaceGridOptions } from "../types";
declare global { declare global {
@ -71,10 +72,23 @@ export class HuiCard extends ReactiveElement {
public getGridOptions(): LovelaceGridOptions { public getGridOptions(): LovelaceGridOptions {
const elementOptions = this.getElementGridOptions(); const elementOptions = this.getElementGridOptions();
const configOptions = this.getConfigGridOptions(); const configOptions = this.getConfigGridOptions();
return { const mergedConfig = {
...elementOptions, ...elementOptions,
...configOptions, ...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 // options provided by the element
@ -119,7 +133,15 @@ export class HuiCard extends ReactiveElement {
} }
private _loadElement(config: LovelaceCardConfig) { 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; this._elementConfig = config;
if (this.hass) { if (this.hass) {
this._element.hass = this.hass; this._element.hass = this.hass;
@ -200,6 +222,7 @@ export class HuiCard extends ReactiveElement {
this._element.preview = this.preview; this._element.preview = this.preview;
// For backwards compatibility // For backwards compatibility
(this._element as any).editMode = this.preview; (this._element as any).editMode = this.preview;
fireEvent(this, "card-updated");
} catch (e: any) { } catch (e: any) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.error(this.config?.type, e); console.error(this.config?.type, e);

View File

@ -1,11 +1,11 @@
import { mdiAlertCircleOutline, mdiAlertOutline } from "@mdi/js";
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 { mdiAlertCircleOutline, mdiAlertOutline } from "@mdi/js"; import "../../../components/ha-card";
import "../../../components/ha-svg-icon";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import type { LovelaceCard, LovelaceGridOptions } 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 = { const ERROR_ICONS = {
warning: mdiAlertOutline, warning: mdiAlertOutline,
@ -30,9 +30,10 @@ export class HuiErrorCard extends LitElement implements LovelaceCard {
public getGridOptions(): LovelaceGridOptions { public getGridOptions(): LovelaceGridOptions {
return { return {
columns: 6, columns: 6,
rows: 1, rows: this.preview ? "auto" : 1,
min_rows: 1, min_rows: 1,
min_columns: 6, min_columns: 6,
fixed_rows: this.preview,
}; };
} }
@ -45,17 +46,24 @@ export class HuiErrorCard extends LitElement implements LovelaceCard {
const error = const error =
this._config?.error || this._config?.error ||
this.hass?.localize("ui.errors.config.configuration_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` return html`
<ha-card class="${this.severity} ${showTitle ? "" : "no-title"}"> <ha-card class="${this.severity} ${showTitle ? "" : "no-title"}">
<div class="icon"> <div class="header">
<slot name="icon"> <div class="icon">
<ha-svg-icon .path=${ERROR_ICONS[this.severity]}></ha-svg-icon> <slot name="icon">
</slot> <ha-svg-icon .path=${ERROR_ICONS[this.severity]}></ha-svg-icon>
</slot>
</div>
${showTitle
? html`<div class="title"><slot>${error}</slot></div>`
: nothing}
</div> </div>
${showTitle ${showMessage && this._config?.message
? html`<div class="title"><slot>${error}</slot></div>` ? html`<div class="message">${this._config.message}</div>`
: nothing} : nothing}
</ha-card> </ha-card>
`; `;
@ -65,10 +73,6 @@ export class HuiErrorCard extends LitElement implements LovelaceCard {
ha-card { ha-card {
height: 100%; height: 100%;
border-width: 0; border-width: 0;
display: flex;
align-items: center;
column-gap: 16px;
padding: 16px;
} }
ha-card::after { ha-card::after {
position: absolute; position: absolute;
@ -81,6 +85,15 @@ export class HuiErrorCard extends LitElement implements LovelaceCard {
content: ""; content: "";
border-radius: var(--ha-card-border-radius, 12px); 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 { .no-title {
justify-content: center; justify-content: center;
} }
@ -90,13 +103,13 @@ export class HuiErrorCard extends LitElement implements LovelaceCard {
text-overflow: ellipsis; text-overflow: ellipsis;
font-weight: var(--ha-font-weight-bold); font-weight: var(--ha-font-weight-bold);
} }
ha-card.warning > .icon { ha-card.warning .icon {
color: var(--warning-color); color: var(--warning-color);
} }
ha-card.warning::after { ha-card.warning::after {
background-color: var(--warning-color); background-color: var(--warning-color);
} }
ha-card.error > .icon { ha-card.error .icon {
color: var(--error-color); color: var(--error-color);
} }
ha-card.error::after { ha-card.error::after {

View File

@ -62,6 +62,8 @@ export interface LovelaceGridOptions {
min_columns?: number; min_columns?: number;
min_rows?: number; min_rows?: number;
max_rows?: number; max_rows?: number;
fixed_rows?: boolean;
fixed_columns?: boolean;
} }
export interface LovelaceCard extends HTMLElement { export interface LovelaceCard extends HTMLElement {