From cf68f25a0378e8e796b8650dcfe68f9d904bba6f Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 19 Jun 2020 01:26:31 +0200 Subject: [PATCH] Don't throw errors in card picker (#6188) --- .../create-element/create-card-element.ts | 12 +++++ .../create-element/create-element-base.ts | 47 ++++++++++++++----- .../editor/card-editor/hui-card-picker.ts | 19 ++++++-- 3 files changed, 60 insertions(+), 18 deletions(-) diff --git a/src/panels/lovelace/create-element/create-card-element.ts b/src/panels/lovelace/create-element/create-card-element.ts index cb5748eecf..23b975e0ff 100644 --- a/src/panels/lovelace/create-element/create-card-element.ts +++ b/src/panels/lovelace/create-element/create-card-element.ts @@ -14,6 +14,7 @@ import "../cards/hui-weather-forecast-card"; import { createLovelaceElement, getLovelaceElementClass, + tryCreateLovelaceElement, } from "./create-element-base"; const ALWAYS_LOADED_TYPES = new Set([ @@ -52,6 +53,17 @@ const LAZY_LOAD_TYPES = { picture: () => import("../cards/hui-picture-card"), }; +// This will not return an error card but will throw the error +export const tryCreateCardElement = (config: LovelaceCardConfig) => + tryCreateLovelaceElement( + "card", + config, + ALWAYS_LOADED_TYPES, + LAZY_LOAD_TYPES, + undefined, + undefined + ); + export const createCardElement = (config: LovelaceCardConfig) => createLovelaceElement( "card", diff --git a/src/panels/lovelace/create-element/create-element-base.ts b/src/panels/lovelace/create-element/create-element-base.ts index 1e9c09cf59..b1afedcb28 100644 --- a/src/panels/lovelace/create-element/create-element-base.ts +++ b/src/panels/lovelace/create-element/create-element-base.ts @@ -73,15 +73,8 @@ const _createElement = ( const element = document.createElement( tag ) as CreateElementConfigTypes[T]["element"]; - try { - // @ts-ignore - element.setConfig(config); - } catch (err) { - // eslint-disable-next-line - console.error(tag, err); - // eslint-disable-next-line @typescript-eslint/no-use-before-define - return _createErrorElement(err.message, config); - } + // @ts-ignore + element.setConfig(config); return element; }; @@ -152,9 +145,37 @@ export const createLovelaceElement = ( domainTypes?: { _domain_not_found: string; [domain: string]: string }, // Default type if no type given. If given, entity types will not work. defaultType?: string +): CreateElementConfigTypes[T]["element"] | HuiErrorCard => { + try { + return tryCreateLovelaceElement( + tagSuffix, + config, + alwaysLoadTypes, + lazyLoadTypes, + domainTypes, + defaultType + ); + } catch (err) { + // eslint-disable-next-line + console.error(tagSuffix, config.type, err); + return _createErrorElement(err.message, config); + } +}; + +export const tryCreateLovelaceElement = < + T extends keyof CreateElementConfigTypes +>( + tagSuffix: T, + config: CreateElementConfigTypes[T]["config"], + alwaysLoadTypes?: Set, + lazyLoadTypes?: { [domain: string]: () => Promise }, + // Allow looking at "entity" in config and mapping that to a type + domainTypes?: { _domain_not_found: string; [domain: string]: string }, + // Default type if no type given. If given, entity types will not work. + defaultType?: string ): CreateElementConfigTypes[T]["element"] | HuiErrorCard => { if (!config || typeof config !== "object") { - return _createErrorElement("Config is not an object", config); + throw new Error("Config is not an object"); } if ( @@ -163,7 +184,7 @@ export const createLovelaceElement = ( // If domain types is given, we can derive a type from "entity" (!domainTypes || !("entity" in config)) ) { - return _createErrorElement("No card type configured.", config); + throw new Error("No card type configured."); } const customTag = config.type ? _getCustomTag(config.type) : undefined; @@ -185,7 +206,7 @@ export const createLovelaceElement = ( } if (type === undefined) { - return _createErrorElement(`No type specified`, config); + throw new Error("No type specified."); } const tag = `hui-${type}-${tagSuffix}`; @@ -199,7 +220,7 @@ export const createLovelaceElement = ( return _createElement(tag, config); } - return _createErrorElement(`Unknown type encountered: ${type}.`, config); + throw new Error(`Unknown type encountered: ${type}`); }; export const getLovelaceElementClass = async < diff --git a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts index 76f4fe5db6..0fea27a87c 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts @@ -27,7 +27,7 @@ import { calcUnusedEntities, computeUsedEntities, } from "../../common/compute-unused-entities"; -import { createCardElement } from "../../create-element/create-card-element"; +import { tryCreateCardElement } from "../../create-element/create-card-element"; import { LovelaceCard } from "../../types"; import { getCardStubConfig } from "../get-card-stub-config"; import { CardPickTarget, Card } from "../types"; @@ -307,8 +307,8 @@ export class HuiCardPicker extends LitElement { fireEvent(this, "config-changed", { config }); } - private _createCardElement(cardConfig: LovelaceCardConfig) { - const element = createCardElement(cardConfig) as LovelaceCard; + private _tryCreateCardElement(cardConfig: LovelaceCardConfig) { + const element = tryCreateCardElement(cardConfig) as LovelaceCard; element.hass = this.hass; element.addEventListener( "ll-rebuild", @@ -325,7 +325,12 @@ export class HuiCardPicker extends LitElement { cardElToReplace: LovelaceCard, config: LovelaceCardConfig ): void { - const newCardEl = this._createCardElement(config); + let newCardEl: LovelaceCard; + try { + newCardEl = this._tryCreateCardElement(config); + } catch (err) { + return; + } if (cardElToReplace.parentElement) { cardElToReplace.parentElement!.replaceChild(newCardEl, cardElToReplace); } @@ -351,7 +356,11 @@ export class HuiCardPicker extends LitElement { ); if (showElement) { - element = this._createCardElement(cardConfig); + try { + element = this._tryCreateCardElement(cardConfig); + } catch (err) { + element = undefined; + } } }