From df2b2e2ace01fb2b6b73f3652e10ba5d7ec0f445 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Tue, 1 Oct 2019 22:18:06 -0500 Subject: [PATCH 01/16] custom badges --- src/data/lovelace.ts | 8 + .../badges/hui-entity-filter-badge.ts | 148 ++++++++++++++++++ src/panels/lovelace/badges/hui-error-badge.ts | 72 +++++++++ .../lovelace/badges/hui-state-label-badge.ts | 43 +++++ src/panels/lovelace/badges/types.ts | 19 +++ .../lovelace/common/create-badge-element.ts | 78 +++++++++ src/panels/lovelace/types.ts | 5 + 7 files changed, 373 insertions(+) create mode 100644 src/panels/lovelace/badges/hui-entity-filter-badge.ts create mode 100644 src/panels/lovelace/badges/hui-error-badge.ts create mode 100644 src/panels/lovelace/badges/hui-state-label-badge.ts create mode 100644 src/panels/lovelace/badges/types.ts create mode 100644 src/panels/lovelace/common/create-badge-element.ts diff --git a/src/data/lovelace.ts b/src/data/lovelace.ts index 103b1d147fb6..e4b4474e3701 100644 --- a/src/data/lovelace.ts +++ b/src/data/lovelace.ts @@ -20,6 +20,14 @@ export interface LovelaceViewConfig { background?: string; } +export interface LovelaceBadgeConfig { + type: string; + entity: string; + name?: string; + icon?: string; + image?: string; +} + export interface LovelaceCardConfig { index?: number; view_index?: number; diff --git a/src/panels/lovelace/badges/hui-entity-filter-badge.ts b/src/panels/lovelace/badges/hui-entity-filter-badge.ts new file mode 100644 index 000000000000..1ed9cf4ef074 --- /dev/null +++ b/src/panels/lovelace/badges/hui-entity-filter-badge.ts @@ -0,0 +1,148 @@ +import { createBadgeElement } from "../common/create-badge-element"; +import { processConfigEntities } from "../common/process-config-entities"; +import { LovelaceBadge } from "../types"; +import { LovelaceBadgeConfig } from "../../../data/lovelace"; +import { EntityFilterEntityConfig } from "../entity-rows/types"; +import { HomeAssistant } from "../../../types"; +import { EntityFilterBadgeConfig } from "./types"; +import { evaluateFilter } from "../common/evaluate-filter"; + +class EntityFilterBadge extends HTMLElement implements LovelaceBadge { + public isPanel?: boolean; + private _element?: LovelaceBadge; + private _config?: EntityFilterBadgeConfig; + private _configEntities?: EntityFilterEntityConfig[]; + private _baseCardConfig?: LovelaceBadgeConfig; + private _hass?: HomeAssistant; + private _oldEntities?: EntityFilterEntityConfig[]; + + public setConfig(config: EntityFilterBadgeConfig): void { + if (!config.entities || !Array.isArray(config.entities)) { + throw new Error("entities must be specified."); + } + + if ( + !(config.state_filter && Array.isArray(config.state_filter)) && + !config.entities.every( + (entity) => + typeof entity === "object" && + entity.state_filter && + Array.isArray(entity.state_filter) + ) + ) { + throw new Error("Incorrect filter config."); + } + + this._config = config; + this._configEntities = undefined; + + if (this.lastChild) { + this.removeChild(this.lastChild); + this._element = undefined; + } + } + + set hass(hass: HomeAssistant) { + if (!hass || !this._config) { + return; + } + + if (!this.haveEntitiesChanged(hass)) { + this._hass = hass; + return; + } + + this._hass = hass; + + if (!this._configEntities) { + this._configEntities = processConfigEntities(this._config.entities); + } + + const entitiesList = this._configEntities.filter((entityConf) => { + const stateObj = hass.states[entityConf.entity]; + + if (!stateObj) { + return false; + } + + if (entityConf.state_filter) { + for (const filter of entityConf.state_filter) { + if (evaluateFilter(stateObj, filter)) { + return true; + } + } + } else { + for (const filter of this._config!.state_filter) { + if (evaluateFilter(stateObj, filter)) { + return true; + } + } + } + + return false; + }); + + if (entitiesList.length === 0) { + this.style.display = "none"; + return; + } + + const element = this._badgeElement(); + + if (!element) { + return; + } + + if (element.tagName !== "HUI-ERROR-CARD") { + const isSame = + this._oldEntities && + entitiesList.length === this._oldEntities.length && + entitiesList.every((entity, idx) => entity === this._oldEntities![idx]); + + if (!isSame) { + this._oldEntities = entitiesList; + element.setConfig({ ...this._baseCardConfig!, entities: entitiesList }); + } + + element.hass = hass; + } + + // Attach element if it has never been attached. + if (!this.lastChild) { + this.appendChild(element); + } + + this.style.display = "block"; + } + + private haveEntitiesChanged(hass: HomeAssistant): boolean { + if (!this._hass) { + return true; + } + + if (!this._configEntities) { + return true; + } + + for (const config of this._configEntities) { + if ( + this._hass.states[config.entity] !== hass.states[config.entity] || + this._hass.localize !== hass.localize + ) { + return true; + } + } + + return false; + } + + private _badgeElement(): LovelaceBadge | undefined { + if (!this._element && this._config) { + const element = createBadgeElement(this._baseCardConfig!); + this._element = element; + } + + return this._element; + } +} +customElements.define("hui-entity-filter-badge", EntityFilterBadge); diff --git a/src/panels/lovelace/badges/hui-error-badge.ts b/src/panels/lovelace/badges/hui-error-badge.ts new file mode 100644 index 000000000000..909843bbd2ed --- /dev/null +++ b/src/panels/lovelace/badges/hui-error-badge.ts @@ -0,0 +1,72 @@ +import { + html, + LitElement, + TemplateResult, + customElement, + property, + css, + CSSResult, +} from "lit-element"; + +import { LovelaceBadge } from "../types"; +import { LovelaceBadgeConfig } from "../../../data/lovelace"; +import { HomeAssistant } from "../../../types"; +import { ErrorBadgeConfig } from "./types"; + +export const createErrorBadgeElement = (config) => { + const el = document.createElement("hui-error-badge"); + el.setConfig(config); + return el; +}; + +export const createErrorBadgeConfig = (error, origConfig) => ({ + type: "error", + error, + origConfig, +}); + +@customElement("hui-error-badge") +export class HuiErrorBadge extends LitElement implements LovelaceBadge { + public hass?: HomeAssistant; + + @property() private _config?: ErrorBadgeConfig; + + public setConfig(config: ErrorBadgeConfig): void { + this._config = config; + } + + protected render(): TemplateResult | void { + if (!this._config) { + return html``; + } + + return html` + ${this._config.error} +
${this._toStr(this._config.origConfig)}
+ `; + } + + static get styles(): CSSResult { + return css` + :host { + display: block; + background-color: #ef5350; + color: white; + padding: 8px; + font-weight: 500; + user-select: text; + cursor: default; + } + `; + } + + private _toStr(config: LovelaceBadgeConfig): string { + return JSON.stringify(config, null, 2); + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-error-badge": HuiErrorBadge; + } +} diff --git a/src/panels/lovelace/badges/hui-state-label-badge.ts b/src/panels/lovelace/badges/hui-state-label-badge.ts new file mode 100644 index 000000000000..4b92ad0591e5 --- /dev/null +++ b/src/panels/lovelace/badges/hui-state-label-badge.ts @@ -0,0 +1,43 @@ +import { + html, + LitElement, + TemplateResult, + customElement, + property, + css, + CSSResult, +} from "lit-element"; + +import "../../../components/ha-card"; + +import { LovelaceBadge } from "../types"; +import { StateLabelBadgeConfig } from "./types"; +import { HomeAssistant } from "../../../types"; + +@customElement("hui-iframe-card") +export class HuiStateLabelBadge extends LitElement implements LovelaceBadge { + @property() public hass?: HomeAssistant; + @property() protected _config?: StateLabelBadgeConfig; + + public setConfig(config: StateLabelBadgeConfig): void { + this._config = config; + } + + protected render(): TemplateResult | void { + if (!this._config || !this.hass) { + return html``; + } + + return html``; + } + + static get styles(): CSSResult { + return css``; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-state-label-badge": HuiStateLabelBadge; + } +} diff --git a/src/panels/lovelace/badges/types.ts b/src/panels/lovelace/badges/types.ts new file mode 100644 index 000000000000..998255f73c8c --- /dev/null +++ b/src/panels/lovelace/badges/types.ts @@ -0,0 +1,19 @@ +import { LovelaceBadgeConfig } from "../../../data/lovelace"; +import { EntityFilterEntityConfig } from "../entity-rows/types"; + +export interface StateLabelBadgeConfig extends LovelaceBadgeConfig { + entity: string; + name?: string; + states?: string[]; +} + +export interface EntityFilterBadgeConfig extends LovelaceBadgeConfig { + type: "entity-filter"; + entities: Array; + state_filter: Array<{ key: string } | string>; +} + +export interface ErrorBadgeConfig extends LovelaceBadgeConfig { + error: string; + origConfig: LovelaceBadgeConfig; +} diff --git a/src/panels/lovelace/common/create-badge-element.ts b/src/panels/lovelace/common/create-badge-element.ts new file mode 100644 index 000000000000..f731e04b577f --- /dev/null +++ b/src/panels/lovelace/common/create-badge-element.ts @@ -0,0 +1,78 @@ +import deepClone from "deep-clone-simple"; + +import { fireEvent } from "../../../common/dom/fire_event"; + +import "../badges/hui-entity-filter-badge"; +import { + createErrorBadgeElement, + createErrorBadgeConfig, + HuiErrorBadge, +} from "../badges/hui-error-badge"; +import "../badges/hui-state-label-card"; +import { LovelaceBadge } from "../types"; +import { LovelaceBadgeConfig } from "../../../data/lovelace"; + +const BADGE_TYPES = new Set(["entity-filter", "error", "state-label"]); +const CUSTOM_TYPE_PREFIX = "custom:"; +const TIMEOUT = 2000; + +const _createElement = ( + tag: string, + config: LovelaceBadgeConfig +): LovelaceBadge | HuiErrorBadge => { + const element = document.createElement(tag) as LovelaceBadge; + try { + element.setConfig(deepClone(config)); + } catch (err) { + // tslint:disable-next-line + console.error(tag, err); + return _createErrorElement(err.message, config); + } + return element; +}; + +const _createErrorElement = ( + error: string, + config: LovelaceBadgeConfig +): HuiErrorBadge => + createErrorBadgeElement(createErrorBadgeConfig(error, config)); + +export const createBadgeElement = ( + config: LovelaceBadgeConfig +): LovelaceBadge | HuiErrorBadge => { + if (!config || typeof config !== "object" || !config.type) { + return _createErrorElement("No badge type configured.", config); + } + + if (config.type.startsWith(CUSTOM_TYPE_PREFIX)) { + const tag = config.type.substr(CUSTOM_TYPE_PREFIX.length); + + if (customElements.get(tag)) { + return _createElement(tag, config); + } + const element = _createErrorElement( + `Custom element doesn't exist: ${tag}.`, + config + ); + element.style.display = "None"; + const timer = window.setTimeout(() => { + element.style.display = ""; + }, TIMEOUT); + + customElements.whenDefined(tag).then(() => { + clearTimeout(timer); + fireEvent(element, "ll-rebuild"); + }); + + return element; + } + + if (!BADGE_TYPES.has(config.type)) { + return _createErrorElement( + `Unknown card type encountered: ${config.type}.`, + config + ); + } + + return _createElement(`hui-${config.type}-badge`, config); +}; diff --git a/src/panels/lovelace/types.ts b/src/panels/lovelace/types.ts index 85f36b1c33c0..b202a9400098 100644 --- a/src/panels/lovelace/types.ts +++ b/src/panels/lovelace/types.ts @@ -18,6 +18,11 @@ export interface Lovelace { saveConfig: (newConfig: LovelaceConfig) => Promise; } +export interface LovelaceBadge extends HTMLElement { + hass?: HomeAssistant; + setConfig(config: LovelaceCardConfig): void; +} + export interface LovelaceCard extends HTMLElement { hass?: HomeAssistant; isPanel?: boolean; From 43f2503ce10391fcd03183d4d4e690f7148d120d Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Wed, 2 Oct 2019 13:38:42 -0500 Subject: [PATCH 02/16] incremental --- src/data/lovelace.ts | 12 ++--- .../badges/hui-entity-filter-badge.ts | 26 ++++++----- .../lovelace/badges/hui-state-label-badge.ts | 44 ++++++++++++++----- src/panels/lovelace/badges/types.ts | 6 --- .../lovelace/common/create-badge-element.ts | 8 +++- .../common/generate-lovelace-config.ts | 3 +- .../editor/view-editor/hui-edit-view.ts | 8 ++-- src/panels/lovelace/types.ts | 8 +++- src/panels/lovelace/views/hui-view.ts | 26 +++++------ 9 files changed, 79 insertions(+), 62 deletions(-) diff --git a/src/data/lovelace.ts b/src/data/lovelace.ts index e4b4474e3701..36eaedbf0e6b 100644 --- a/src/data/lovelace.ts +++ b/src/data/lovelace.ts @@ -1,5 +1,6 @@ import { HomeAssistant } from "../types"; import { Connection, getCollection } from "home-assistant-js-websocket"; +import { EntityConfig } from "../panels/lovelace/entity-rows/types"; export interface LovelaceConfig { title?: string; @@ -11,7 +12,7 @@ export interface LovelaceConfig { export interface LovelaceViewConfig { index?: number; title?: string; - badges?: string[]; + badges?: LovelaceBadgeConfig[]; cards?: LovelaceCardConfig[]; path?: string; icon?: string; @@ -20,13 +21,8 @@ export interface LovelaceViewConfig { background?: string; } -export interface LovelaceBadgeConfig { - type: string; - entity: string; - name?: string; - icon?: string; - image?: string; -} +// tslint:disable-next-line: no-empty-interface +export interface LovelaceBadgeConfig extends EntityConfig {} export interface LovelaceCardConfig { index?: number; diff --git a/src/panels/lovelace/badges/hui-entity-filter-badge.ts b/src/panels/lovelace/badges/hui-entity-filter-badge.ts index 1ed9cf4ef074..67438045a085 100644 --- a/src/panels/lovelace/badges/hui-entity-filter-badge.ts +++ b/src/panels/lovelace/badges/hui-entity-filter-badge.ts @@ -93,19 +93,21 @@ class EntityFilterBadge extends HTMLElement implements LovelaceBadge { return; } - if (element.tagName !== "HUI-ERROR-CARD") { - const isSame = - this._oldEntities && - entitiesList.length === this._oldEntities.length && - entitiesList.every((entity, idx) => entity === this._oldEntities![idx]); - - if (!isSame) { - this._oldEntities = entitiesList; - element.setConfig({ ...this._baseCardConfig!, entities: entitiesList }); - } + // TODO Create badgeElements for each entity - element.hass = hass; - } + // if (element.tagName !== "HUI-ERROR-CARD") { + // const isSame = + // this._oldEntities && + // entitiesList.length === this._oldEntities.length && + // entitiesList.every((entity, idx) => entity === this._oldEntities![idx]); + + // if (!isSame) { + // this._oldEntities = entitiesList; + // element.setConfig({ ...this._baseCardConfig!, entities: entitiesList }); + // } + + // element.hass = hass; + // } // Attach element if it has never been attached. if (!this.lastChild) { diff --git a/src/panels/lovelace/badges/hui-state-label-badge.ts b/src/panels/lovelace/badges/hui-state-label-badge.ts index 4b92ad0591e5..8da1b9452e4d 100644 --- a/src/panels/lovelace/badges/hui-state-label-badge.ts +++ b/src/panels/lovelace/badges/hui-state-label-badge.ts @@ -4,22 +4,22 @@ import { TemplateResult, customElement, property, - css, - CSSResult, } from "lit-element"; -import "../../../components/ha-card"; +import "../../../components/entity/ha-state-label-badge"; +import "../components/hui-warning-element"; import { LovelaceBadge } from "../types"; -import { StateLabelBadgeConfig } from "./types"; import { HomeAssistant } from "../../../types"; +import { computeStateName } from "../../../common/entity/compute_state_name"; +import { LovelaceBadgeConfig } from "../../../data/lovelace"; -@customElement("hui-iframe-card") +@customElement("hui-state-label-badge") export class HuiStateLabelBadge extends LitElement implements LovelaceBadge { @property() public hass?: HomeAssistant; - @property() protected _config?: StateLabelBadgeConfig; + @property() protected _config?: LovelaceBadgeConfig; - public setConfig(config: StateLabelBadgeConfig): void { + public setConfig(config: LovelaceBadgeConfig): void { this._config = config; } @@ -28,11 +28,33 @@ export class HuiStateLabelBadge extends LitElement implements LovelaceBadge { return html``; } - return html``; - } + const stateObj = this.hass.states[this._config.entity!]; + + if (!stateObj) { + return html` + + `; + } - static get styles(): CSSResult { - return css``; + return html` + + `; } } diff --git a/src/panels/lovelace/badges/types.ts b/src/panels/lovelace/badges/types.ts index 998255f73c8c..acd037a49685 100644 --- a/src/panels/lovelace/badges/types.ts +++ b/src/panels/lovelace/badges/types.ts @@ -1,12 +1,6 @@ import { LovelaceBadgeConfig } from "../../../data/lovelace"; import { EntityFilterEntityConfig } from "../entity-rows/types"; -export interface StateLabelBadgeConfig extends LovelaceBadgeConfig { - entity: string; - name?: string; - states?: string[]; -} - export interface EntityFilterBadgeConfig extends LovelaceBadgeConfig { type: "entity-filter"; entities: Array; diff --git a/src/panels/lovelace/common/create-badge-element.ts b/src/panels/lovelace/common/create-badge-element.ts index f731e04b577f..6cdc8f4ef654 100644 --- a/src/panels/lovelace/common/create-badge-element.ts +++ b/src/panels/lovelace/common/create-badge-element.ts @@ -8,7 +8,7 @@ import { createErrorBadgeConfig, HuiErrorBadge, } from "../badges/hui-error-badge"; -import "../badges/hui-state-label-card"; +import "../badges/hui-state-label-badge"; import { LovelaceBadge } from "../types"; import { LovelaceBadgeConfig } from "../../../data/lovelace"; @@ -40,10 +40,14 @@ const _createErrorElement = ( export const createBadgeElement = ( config: LovelaceBadgeConfig ): LovelaceBadge | HuiErrorBadge => { - if (!config || typeof config !== "object" || !config.type) { + if (!config || typeof config !== "object") { return _createErrorElement("No badge type configured.", config); } + if (!config.type) { + config.type = "state-label"; + } + if (config.type.startsWith(CUSTOM_TYPE_PREFIX)) { const tag = config.type.substr(CUSTOM_TYPE_PREFIX.length); diff --git a/src/panels/lovelace/common/generate-lovelace-config.ts b/src/panels/lovelace/common/generate-lovelace-config.ts index de86979f8324..3f1a3da723d6 100644 --- a/src/panels/lovelace/common/generate-lovelace-config.ts +++ b/src/panels/lovelace/common/generate-lovelace-config.ts @@ -34,6 +34,7 @@ import { subscribeEntityRegistry, EntityRegistryEntry, } from "../../../data/entity_registry"; +import { processEditorEntities } from "../editor/process-editor-entities"; const DEFAULT_VIEW_ENTITY_ID = "group.default_view"; const DOMAINS_BADGES = [ @@ -315,7 +316,7 @@ const generateViewConfig = ( const view: LovelaceViewConfig = { path, title, - badges, + badges: processEditorEntities(badges), cards, }; diff --git a/src/panels/lovelace/editor/view-editor/hui-edit-view.ts b/src/panels/lovelace/editor/view-editor/hui-edit-view.ts index 55d68a17023b..6e7ccd28eb44 100644 --- a/src/panels/lovelace/editor/view-editor/hui-edit-view.ts +++ b/src/panels/lovelace/editor/view-editor/hui-edit-view.ts @@ -26,11 +26,11 @@ import { HomeAssistant } from "../../../../types"; import { LovelaceViewConfig, LovelaceCardConfig, + LovelaceBadgeConfig, } from "../../../../data/lovelace"; import { fireEvent } from "../../../../common/dom/fire_event"; import { EntitiesEditorEvent, ViewEditEvent } from "../types"; import { processEditorEntities } from "../process-editor-entities"; -import { EntityConfig } from "../../entity-rows/types"; import { navigate } from "../../../../common/navigate"; import { Lovelace } from "../../types"; import { deleteView, addView, replaceView } from "../config-util"; @@ -45,7 +45,7 @@ export class HuiEditView extends LitElement { @property() private _config?: LovelaceViewConfig; - @property() private _badges?: EntityConfig[]; + @property() private _badges?: LovelaceBadgeConfig[]; @property() private _cards?: LovelaceCardConfig[]; @@ -216,7 +216,7 @@ export class HuiEditView extends LitElement { const viewConf: LovelaceViewConfig = { cards: this._cards, - badges: this._badges!.map((entityConf) => entityConf.entity), + badges: this._badges, ...this._config, }; @@ -246,7 +246,7 @@ export class HuiEditView extends LitElement { if (!this._badges || !this.hass || !ev.detail || !ev.detail.entities) { return; } - this._badges = ev.detail.entities; + this._badges = processEditorEntities(ev.detail.entities); } private _isConfigChanged(): boolean { diff --git a/src/panels/lovelace/types.ts b/src/panels/lovelace/types.ts index b202a9400098..85c0c54ed5e7 100644 --- a/src/panels/lovelace/types.ts +++ b/src/panels/lovelace/types.ts @@ -1,5 +1,9 @@ import { HomeAssistant } from "../../types"; -import { LovelaceCardConfig, LovelaceConfig } from "../../data/lovelace"; +import { + LovelaceCardConfig, + LovelaceConfig, + LovelaceBadgeConfig, +} from "../../data/lovelace"; declare global { // tslint:disable-next-line @@ -20,7 +24,7 @@ export interface Lovelace { export interface LovelaceBadge extends HTMLElement { hass?: HomeAssistant; - setConfig(config: LovelaceCardConfig): void; + setConfig(config: LovelaceBadgeConfig): void; } export interface LovelaceCard extends HTMLElement { diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index 5edef27a2515..755f1fd4c1d4 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -8,22 +8,19 @@ import { import "../../../components/entity/ha-state-label-badge"; // This one is for types -// tslint:disable-next-line -import { HaStateLabelBadge } from "../../../components/entity/ha-state-label-badge"; import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import { LovelaceViewConfig, LovelaceCardConfig } from "../../../data/lovelace"; import { HomeAssistant } from "../../../types"; import { classMap } from "lit-html/directives/class-map"; -import { Lovelace, LovelaceCard } from "../types"; +import { Lovelace, LovelaceCard, LovelaceBadge } from "../types"; import { createCardElement } from "../common/create-card-element"; import { computeCardSize } from "../common/compute-card-size"; import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog"; import { HuiErrorCard } from "../cards/hui-error-card"; - import { computeRTL } from "../../../common/util/compute_rtl"; -import { processConfigEntities } from "../common/process-config-entities"; +import { createBadgeElement } from "../common/create-badge-element"; let editCodeLoaded = false; @@ -51,7 +48,7 @@ export class HUIView extends LitElement { public columns?: number; public index?: number; private _cards: Array; - private _badges: Array<{ element: HaStateLabelBadge; entityId: string }>; + private _badges: Array<{ element: LovelaceBadge; entityId: string }>; static get properties(): PropertyDeclarations { return { @@ -209,9 +206,8 @@ export class HUIView extends LitElement { this._createBadges(lovelace.config.views[this.index!]); } else if (hassChanged) { this._badges.forEach((badge) => { - const { element, entityId } = badge; + const { element } = badge; element.hass = hass; - element.state = hass.states[entityId]; }); } @@ -262,16 +258,14 @@ export class HUIView extends LitElement { } const elements: HUIView["_badges"] = []; - // It's possible that a null value was stored as a badge entry - const badges = processConfigEntities(config.badges.filter(Boolean)); - for (const badge of badges) { - const element = document.createElement("ha-state-label-badge"); + for (const badge of config.badges) { + const element = createBadgeElement(badge); const entityId = badge.entity; element.hass = this.hass; - element.state = this.hass!.states[entityId]; - element.name = badge.name; - element.icon = badge.icon; - element.image = badge.image; + // element.state = this.hass!.states[entityId]; + // element.name = badge.name; + // element.icon = badge.icon; + // element.image = badge.image; elements.push({ element, entityId }); root.appendChild(element); } From 2fd3c1639c530a92295e2417d5bfdd16ae64476f Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Wed, 2 Oct 2019 23:06:55 -0500 Subject: [PATCH 03/16] functional --- .../badges/hui-entity-filter-badge.ts | 55 ++++++++----------- src/panels/lovelace/badges/hui-error-badge.ts | 28 ++++------ .../lovelace/badges/hui-state-label-badge.ts | 16 +----- src/panels/lovelace/badges/types.ts | 1 - .../lovelace/common/create-badge-element.ts | 21 ++----- src/panels/lovelace/views/hui-view.ts | 4 +- 6 files changed, 46 insertions(+), 79 deletions(-) diff --git a/src/panels/lovelace/badges/hui-entity-filter-badge.ts b/src/panels/lovelace/badges/hui-entity-filter-badge.ts index 67438045a085..f1052c2a3aac 100644 --- a/src/panels/lovelace/badges/hui-entity-filter-badge.ts +++ b/src/panels/lovelace/badges/hui-entity-filter-badge.ts @@ -1,7 +1,6 @@ import { createBadgeElement } from "../common/create-badge-element"; import { processConfigEntities } from "../common/process-config-entities"; import { LovelaceBadge } from "../types"; -import { LovelaceBadgeConfig } from "../../../data/lovelace"; import { EntityFilterEntityConfig } from "../entity-rows/types"; import { HomeAssistant } from "../../../types"; import { EntityFilterBadgeConfig } from "./types"; @@ -9,10 +8,9 @@ import { evaluateFilter } from "../common/evaluate-filter"; class EntityFilterBadge extends HTMLElement implements LovelaceBadge { public isPanel?: boolean; - private _element?: LovelaceBadge; + private _elements?: LovelaceBadge[]; private _config?: EntityFilterBadgeConfig; private _configEntities?: EntityFilterEntityConfig[]; - private _baseCardConfig?: LovelaceBadgeConfig; private _hass?: HomeAssistant; private _oldEntities?: EntityFilterEntityConfig[]; @@ -38,7 +36,7 @@ class EntityFilterBadge extends HTMLElement implements LovelaceBadge { if (this.lastChild) { this.removeChild(this.lastChild); - this._element = undefined; + this._elements = undefined; } } @@ -87,34 +85,36 @@ class EntityFilterBadge extends HTMLElement implements LovelaceBadge { return; } - const element = this._badgeElement(); + const isSame = + this._oldEntities && + entitiesList.length === this._oldEntities.length && + entitiesList.every((entity, idx) => entity === this._oldEntities![idx]); - if (!element) { - return; + if (!isSame) { + this._elements = []; + for (const badgeConfig of entitiesList) { + const element = createBadgeElement(badgeConfig); + this._elements.push(element); + } + this._oldEntities = entitiesList; } - // TODO Create badgeElements for each entity - - // if (element.tagName !== "HUI-ERROR-CARD") { - // const isSame = - // this._oldEntities && - // entitiesList.length === this._oldEntities.length && - // entitiesList.every((entity, idx) => entity === this._oldEntities![idx]); - - // if (!isSame) { - // this._oldEntities = entitiesList; - // element.setConfig({ ...this._baseCardConfig!, entities: entitiesList }); - // } + if (!this._elements) { + return; + } - // element.hass = hass; - // } + for (const element of this._elements) { + element.hass = hass; + } // Attach element if it has never been attached. if (!this.lastChild) { - this.appendChild(element); + for (const element of this._elements) { + this.appendChild(element); + } } - this.style.display = "block"; + this.style.display = "inline"; } private haveEntitiesChanged(hass: HomeAssistant): boolean { @@ -137,14 +137,5 @@ class EntityFilterBadge extends HTMLElement implements LovelaceBadge { return false; } - - private _badgeElement(): LovelaceBadge | undefined { - if (!this._element && this._config) { - const element = createBadgeElement(this._baseCardConfig!); - this._element = element; - } - - return this._element; - } } customElements.define("hui-entity-filter-badge", EntityFilterBadge); diff --git a/src/panels/lovelace/badges/hui-error-badge.ts b/src/panels/lovelace/badges/hui-error-badge.ts index 909843bbd2ed..a4998ffc0a99 100644 --- a/src/panels/lovelace/badges/hui-error-badge.ts +++ b/src/panels/lovelace/badges/hui-error-badge.ts @@ -9,20 +9,20 @@ import { } from "lit-element"; import { LovelaceBadge } from "../types"; -import { LovelaceBadgeConfig } from "../../../data/lovelace"; import { HomeAssistant } from "../../../types"; import { ErrorBadgeConfig } from "./types"; +import "../../../components/ha-label-badge"; + export const createErrorBadgeElement = (config) => { const el = document.createElement("hui-error-badge"); el.setConfig(config); return el; }; -export const createErrorBadgeConfig = (error, origConfig) => ({ +export const createErrorBadgeConfig = (error) => ({ type: "error", error, - origConfig, }); @customElement("hui-error-badge") @@ -41,28 +41,22 @@ export class HuiErrorBadge extends LitElement implements LovelaceBadge { } return html` - ${this._config.error} -
${this._toStr(this._config.origConfig)}
+ `; } static get styles(): CSSResult { return css` - :host { - display: block; - background-color: #ef5350; - color: white; - padding: 8px; - font-weight: 500; - user-select: text; - cursor: default; + .warning { + --ha-label-badge-color: var(--label-badge-yellow, #fce588); } `; } - - private _toStr(config: LovelaceBadgeConfig): string { - return JSON.stringify(config, null, 2); - } } declare global { diff --git a/src/panels/lovelace/badges/hui-state-label-badge.ts b/src/panels/lovelace/badges/hui-state-label-badge.ts index 8da1b9452e4d..6f92458f6a2e 100644 --- a/src/panels/lovelace/badges/hui-state-label-badge.ts +++ b/src/panels/lovelace/badges/hui-state-label-badge.ts @@ -30,24 +30,14 @@ export class HuiStateLabelBadge extends LitElement implements LovelaceBadge { const stateObj = this.hass.states[this._config.entity!]; - if (!stateObj) { - return html` - - `; - } - return html` - createErrorBadgeElement(createErrorBadgeConfig(error, config)); +const _createErrorElement = (error: string): HuiErrorBadge => + createErrorBadgeElement(createErrorBadgeConfig(error)); export const createBadgeElement = ( config: LovelaceBadgeConfig ): LovelaceBadge | HuiErrorBadge => { if (!config || typeof config !== "object") { - return _createErrorElement("No badge type configured.", config); + return _createErrorElement("No config"); } if (!config.type) { @@ -54,10 +51,7 @@ export const createBadgeElement = ( if (customElements.get(tag)) { return _createElement(tag, config); } - const element = _createErrorElement( - `Custom element doesn't exist: ${tag}.`, - config - ); + const element = _createErrorElement(`Type doesn't exist: ${tag}`); element.style.display = "None"; const timer = window.setTimeout(() => { element.style.display = ""; @@ -72,10 +66,7 @@ export const createBadgeElement = ( } if (!BADGE_TYPES.has(config.type)) { - return _createErrorElement( - `Unknown card type encountered: ${config.type}.`, - config - ); + return _createErrorElement(`Unknown type: ${config.type}`); } return _createElement(`hui-${config.type}-badge`, config); diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index 755f1fd4c1d4..4cb26b0aac69 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -21,6 +21,7 @@ import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog" import { HuiErrorCard } from "../cards/hui-error-card"; import { computeRTL } from "../../../common/util/compute_rtl"; import { createBadgeElement } from "../common/create-badge-element"; +import { processEditorEntities } from "../editor/process-editor-entities"; let editCodeLoaded = false; @@ -258,7 +259,8 @@ export class HUIView extends LitElement { } const elements: HUIView["_badges"] = []; - for (const badge of config.badges) { + const badges = processEditorEntities(config.badges); + for (const badge of badges) { const element = createBadgeElement(badge); const entityId = badge.entity; element.hass = this.hass; From 23e3880ead24688e383e1d4d7d6899931f8019f8 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Wed, 2 Oct 2019 23:11:08 -0500 Subject: [PATCH 04/16] cleanup --- src/panels/lovelace/views/hui-view.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index 4cb26b0aac69..dfa23f361f03 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -264,10 +264,6 @@ export class HUIView extends LitElement { const element = createBadgeElement(badge); const entityId = badge.entity; element.hass = this.hass; - // element.state = this.hass!.states[entityId]; - // element.name = badge.name; - // element.icon = badge.icon; - // element.image = badge.image; elements.push({ element, entityId }); root.appendChild(element); } From 4bccd5d1637d4bcc85315c8b320d125fc9086ca9 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Wed, 2 Oct 2019 23:16:08 -0500 Subject: [PATCH 05/16] cleanup --- src/panels/lovelace/views/hui-view.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index dfa23f361f03..d7707dd65d82 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -21,7 +21,7 @@ import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog" import { HuiErrorCard } from "../cards/hui-error-card"; import { computeRTL } from "../../../common/util/compute_rtl"; import { createBadgeElement } from "../common/create-badge-element"; -import { processEditorEntities } from "../editor/process-editor-entities"; +import { processConfigEntities } from "../common/process-config-entities"; let editCodeLoaded = false; @@ -259,7 +259,7 @@ export class HUIView extends LitElement { } const elements: HUIView["_badges"] = []; - const badges = processEditorEntities(config.badges); + const badges = processConfigEntities(config.badges); for (const badge of badges) { const element = createBadgeElement(badge); const entityId = badge.entity; From d6b5ca0c29153606ba2706c0b9808ae5b0d0194b Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Thu, 3 Oct 2019 17:48:38 -0500 Subject: [PATCH 06/16] address review comments --- src/data/lovelace.ts | 2 +- .../lovelace/badges/hui-entity-filter-badge.ts | 7 ++----- src/panels/lovelace/badges/hui-error-badge.ts | 3 +-- .../lovelace/common/create-badge-element.ts | 16 +++++++++------- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/data/lovelace.ts b/src/data/lovelace.ts index 36eaedbf0e6b..1c799e824daf 100644 --- a/src/data/lovelace.ts +++ b/src/data/lovelace.ts @@ -12,7 +12,7 @@ export interface LovelaceConfig { export interface LovelaceViewConfig { index?: number; title?: string; - badges?: LovelaceBadgeConfig[]; + badges?: Array; cards?: LovelaceCardConfig[]; path?: string; icon?: string; diff --git a/src/panels/lovelace/badges/hui-entity-filter-badge.ts b/src/panels/lovelace/badges/hui-entity-filter-badge.ts index f1052c2a3aac..04df990ec842 100644 --- a/src/panels/lovelace/badges/hui-entity-filter-badge.ts +++ b/src/panels/lovelace/badges/hui-entity-filter-badge.ts @@ -122,15 +122,12 @@ class EntityFilterBadge extends HTMLElement implements LovelaceBadge { return true; } - if (!this._configEntities) { + if (!this._configEntities || this._hass.localize !== hass.localize) { return true; } for (const config of this._configEntities) { - if ( - this._hass.states[config.entity] !== hass.states[config.entity] || - this._hass.localize !== hass.localize - ) { + if (this._hass.states[config.entity] !== hass.states[config.entity]) { return true; } } diff --git a/src/panels/lovelace/badges/hui-error-badge.ts b/src/panels/lovelace/badges/hui-error-badge.ts index a4998ffc0a99..ec9c3d38bea7 100644 --- a/src/panels/lovelace/badges/hui-error-badge.ts +++ b/src/panels/lovelace/badges/hui-error-badge.ts @@ -42,7 +42,6 @@ export class HuiErrorBadge extends LitElement implements LovelaceBadge { return html` Date: Thu, 3 Oct 2019 17:56:10 -0500 Subject: [PATCH 07/16] address more comments --- src/panels/lovelace/common/create-badge-element.ts | 6 ++---- src/panels/lovelace/views/hui-view.ts | 8 +++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/panels/lovelace/common/create-badge-element.ts b/src/panels/lovelace/common/create-badge-element.ts index 2506d04a58c7..cf59cdf7b50e 100644 --- a/src/panels/lovelace/common/create-badge-element.ts +++ b/src/panels/lovelace/common/create-badge-element.ts @@ -1,14 +1,13 @@ import deepClone from "deep-clone-simple"; -import { fireEvent } from "../../../common/dom/fire_event"; - import "../badges/hui-entity-filter-badge"; +import "../badges/hui-state-label-badge"; + import { createErrorBadgeElement, createErrorBadgeConfig, HuiErrorBadge, } from "../badges/hui-error-badge"; -import "../badges/hui-state-label-badge"; import { LovelaceBadge } from "../types"; import { LovelaceBadgeConfig } from "../../../data/lovelace"; @@ -61,7 +60,6 @@ export const createBadgeElement = ( customElements.whenDefined(tag).then(() => { clearTimeout(timer); - fireEvent(element, "ll-rebuild"); }); return element; diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index d7707dd65d82..6ae9899b0bd9 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -49,7 +49,7 @@ export class HUIView extends LitElement { public columns?: number; public index?: number; private _cards: Array; - private _badges: Array<{ element: LovelaceBadge; entityId: string }>; + private _badges: LovelaceBadge[]; static get properties(): PropertyDeclarations { return { @@ -207,8 +207,7 @@ export class HUIView extends LitElement { this._createBadges(lovelace.config.views[this.index!]); } else if (hassChanged) { this._badges.forEach((badge) => { - const { element } = badge; - element.hass = hass; + badge.hass = hass; }); } @@ -262,9 +261,8 @@ export class HUIView extends LitElement { const badges = processConfigEntities(config.badges); for (const badge of badges) { const element = createBadgeElement(badge); - const entityId = badge.entity; element.hass = this.hass; - elements.push({ element, entityId }); + elements.push(element); root.appendChild(element); } this._badges = elements; From 693b8e252fa3ac78f660ff3cae08c2ec45bef240 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Fri, 4 Oct 2019 13:32:20 -0500 Subject: [PATCH 08/16] address review comments --- src/panels/lovelace/badges/hui-entity-filter-badge.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/panels/lovelace/badges/hui-entity-filter-badge.ts b/src/panels/lovelace/badges/hui-entity-filter-badge.ts index 04df990ec842..43299f98cd44 100644 --- a/src/panels/lovelace/badges/hui-entity-filter-badge.ts +++ b/src/panels/lovelace/badges/hui-entity-filter-badge.ts @@ -47,6 +47,13 @@ class EntityFilterBadge extends HTMLElement implements LovelaceBadge { if (!this.haveEntitiesChanged(hass)) { this._hass = hass; + + if (this._elements) { + for (const element of this._elements) { + element.hass = hass; + } + } + return; } From ecac1325b5ad76039f93946f5ff8cb0a708e271a Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Sat, 5 Oct 2019 17:05:40 -0500 Subject: [PATCH 09/16] address review comments --- src/data/lovelace.ts | 4 +++- .../lovelace/badges/hui-state-label-badge.ts | 18 ++++++++---------- src/panels/lovelace/badges/types.ts | 7 +++++++ .../lovelace/common/create-badge-element.ts | 4 ++-- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/data/lovelace.ts b/src/data/lovelace.ts index 1c799e824daf..17f0fa4e00e2 100644 --- a/src/data/lovelace.ts +++ b/src/data/lovelace.ts @@ -22,7 +22,9 @@ export interface LovelaceViewConfig { } // tslint:disable-next-line: no-empty-interface -export interface LovelaceBadgeConfig extends EntityConfig {} +export interface LovelaceBadgeConfig { + type?: string; +} export interface LovelaceCardConfig { index?: number; diff --git a/src/panels/lovelace/badges/hui-state-label-badge.ts b/src/panels/lovelace/badges/hui-state-label-badge.ts index 6f92458f6a2e..acef603a0a90 100644 --- a/src/panels/lovelace/badges/hui-state-label-badge.ts +++ b/src/panels/lovelace/badges/hui-state-label-badge.ts @@ -12,14 +12,14 @@ import "../components/hui-warning-element"; import { LovelaceBadge } from "../types"; import { HomeAssistant } from "../../../types"; import { computeStateName } from "../../../common/entity/compute_state_name"; -import { LovelaceBadgeConfig } from "../../../data/lovelace"; +import { StateLabelBadgeConfig } from "./types"; @customElement("hui-state-label-badge") export class HuiStateLabelBadge extends LitElement implements LovelaceBadge { @property() public hass?: HomeAssistant; - @property() protected _config?: LovelaceBadgeConfig; + @property() protected _config?: StateLabelBadgeConfig; - public setConfig(config: LovelaceBadgeConfig): void { + public setConfig(config: StateLabelBadgeConfig): void { this._config = config; } @@ -34,13 +34,11 @@ export class HuiStateLabelBadge extends LitElement implements LovelaceBadge { diff --git a/src/panels/lovelace/badges/types.ts b/src/panels/lovelace/badges/types.ts index dee04b90035c..e462a0a4eeaa 100644 --- a/src/panels/lovelace/badges/types.ts +++ b/src/panels/lovelace/badges/types.ts @@ -10,3 +10,10 @@ export interface EntityFilterBadgeConfig extends LovelaceBadgeConfig { export interface ErrorBadgeConfig extends LovelaceBadgeConfig { error: string; } + +export interface StateLabelBadgeConfig extends LovelaceBadgeConfig { + entity: string; + name?: string; + icon?: string; + image?: string; +} diff --git a/src/panels/lovelace/common/create-badge-element.ts b/src/panels/lovelace/common/create-badge-element.ts index cf59cdf7b50e..f23e8f6b045d 100644 --- a/src/panels/lovelace/common/create-badge-element.ts +++ b/src/panels/lovelace/common/create-badge-element.ts @@ -21,7 +21,7 @@ const _createElement = ( ): LovelaceBadge | HuiErrorBadge => { const element = document.createElement(tag) as LovelaceBadge; try { - element.setConfig(deepClone(config)); + element.setConfig(config); } catch (err) { // tslint:disable-next-line console.error(tag, err); @@ -35,7 +35,7 @@ const _createErrorElement = (error: string): HuiErrorBadge => export const createBadgeElement = ( config: LovelaceBadgeConfig -): LovelaceBadge | HuiErrorBadge => { +): LovelaceBadge => { if (!config || typeof config !== "object") { return _createErrorElement("No config"); } From 3e35bb37669b3dc4e6d7822674be34c522f1bd33 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Sat, 5 Oct 2019 17:20:22 -0500 Subject: [PATCH 10/16] cleanup --- src/data/lovelace.ts | 1 - src/panels/lovelace/common/create-badge-element.ts | 2 -- src/panels/lovelace/views/hui-view.ts | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/data/lovelace.ts b/src/data/lovelace.ts index 17f0fa4e00e2..41ad30ef728b 100644 --- a/src/data/lovelace.ts +++ b/src/data/lovelace.ts @@ -1,6 +1,5 @@ import { HomeAssistant } from "../types"; import { Connection, getCollection } from "home-assistant-js-websocket"; -import { EntityConfig } from "../panels/lovelace/entity-rows/types"; export interface LovelaceConfig { title?: string; diff --git a/src/panels/lovelace/common/create-badge-element.ts b/src/panels/lovelace/common/create-badge-element.ts index f23e8f6b045d..2da37939a7ad 100644 --- a/src/panels/lovelace/common/create-badge-element.ts +++ b/src/panels/lovelace/common/create-badge-element.ts @@ -1,5 +1,3 @@ -import deepClone from "deep-clone-simple"; - import "../badges/hui-entity-filter-badge"; import "../badges/hui-state-label-badge"; diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index 6ae9899b0bd9..6fdf97c9d0f3 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -258,7 +258,7 @@ export class HUIView extends LitElement { } const elements: HUIView["_badges"] = []; - const badges = processConfigEntities(config.badges); + const badges = processConfigEntities(config.badges as any); for (const badge of badges) { const element = createBadgeElement(badge); element.hass = this.hass; From 2d5258e1340093bce4e13fa70b611cf0ee6a2222 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Sun, 6 Oct 2019 22:45:19 -0500 Subject: [PATCH 11/16] address review comments --- src/data/lovelace.ts | 1 - src/panels/lovelace/badges/hui-entity-filter-badge.ts | 1 - src/panels/lovelace/badges/hui-error-badge.ts | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/data/lovelace.ts b/src/data/lovelace.ts index 41ad30ef728b..080b701e3c1e 100644 --- a/src/data/lovelace.ts +++ b/src/data/lovelace.ts @@ -20,7 +20,6 @@ export interface LovelaceViewConfig { background?: string; } -// tslint:disable-next-line: no-empty-interface export interface LovelaceBadgeConfig { type?: string; } diff --git a/src/panels/lovelace/badges/hui-entity-filter-badge.ts b/src/panels/lovelace/badges/hui-entity-filter-badge.ts index 43299f98cd44..a94921dc7e63 100644 --- a/src/panels/lovelace/badges/hui-entity-filter-badge.ts +++ b/src/panels/lovelace/badges/hui-entity-filter-badge.ts @@ -7,7 +7,6 @@ import { EntityFilterBadgeConfig } from "./types"; import { evaluateFilter } from "../common/evaluate-filter"; class EntityFilterBadge extends HTMLElement implements LovelaceBadge { - public isPanel?: boolean; private _elements?: LovelaceBadge[]; private _config?: EntityFilterBadgeConfig; private _configEntities?: EntityFilterEntityConfig[]; diff --git a/src/panels/lovelace/badges/hui-error-badge.ts b/src/panels/lovelace/badges/hui-error-badge.ts index ec9c3d38bea7..9c20ceff39aa 100644 --- a/src/panels/lovelace/badges/hui-error-badge.ts +++ b/src/panels/lovelace/badges/hui-error-badge.ts @@ -52,7 +52,7 @@ export class HuiErrorBadge extends LitElement implements LovelaceBadge { static get styles(): CSSResult { return css` :host { - --ha-label-badge-color: var(--label-badge-yellow, #fce588); + --ha-label-badge-color: var(--label-badge-red, #fce588); } `; } From 170472a0271cdc9d5ef7840ef2f714580e230cb8 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Mon, 14 Oct 2019 22:00:09 -0500 Subject: [PATCH 12/16] address comments --- src/data/lovelace.ts | 1 + .../badges/hui-entity-filter-badge.ts | 19 ++++------- .../lovelace/common/create-badge-element.ts | 4 ++- .../editor/view-editor/hui-edit-view.ts | 4 +-- src/panels/lovelace/types.ts | 1 + src/panels/lovelace/views/hui-view.ts | 34 ++++++++++++++++++- 6 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/data/lovelace.ts b/src/data/lovelace.ts index 080b701e3c1e..c3d1316a3128 100644 --- a/src/data/lovelace.ts +++ b/src/data/lovelace.ts @@ -22,6 +22,7 @@ export interface LovelaceViewConfig { export interface LovelaceBadgeConfig { type?: string; + [key: string]: any; } export interface LovelaceCardConfig { diff --git a/src/panels/lovelace/badges/hui-entity-filter-badge.ts b/src/panels/lovelace/badges/hui-entity-filter-badge.ts index a94921dc7e63..747f535900c8 100644 --- a/src/panels/lovelace/badges/hui-entity-filter-badge.ts +++ b/src/panels/lovelace/badges/hui-entity-filter-badge.ts @@ -44,20 +44,18 @@ class EntityFilterBadge extends HTMLElement implements LovelaceBadge { return; } - if (!this.haveEntitiesChanged(hass)) { - this._hass = hass; + this._hass = hass; - if (this._elements) { - for (const element of this._elements) { - element.hass = hass; - } + if (this._elements) { + for (const element of this._elements) { + element.hass = hass; } + } + if (!this.haveEntitiesChanged(hass)) { return; } - this._hass = hass; - if (!this._configEntities) { this._configEntities = processConfigEntities(this._config.entities); } @@ -100,6 +98,7 @@ class EntityFilterBadge extends HTMLElement implements LovelaceBadge { this._elements = []; for (const badgeConfig of entitiesList) { const element = createBadgeElement(badgeConfig); + element.hass = hass; this._elements.push(element); } this._oldEntities = entitiesList; @@ -109,10 +108,6 @@ class EntityFilterBadge extends HTMLElement implements LovelaceBadge { return; } - for (const element of this._elements) { - element.hass = hass; - } - // Attach element if it has never been attached. if (!this.lastChild) { for (const element of this._elements) { diff --git a/src/panels/lovelace/common/create-badge-element.ts b/src/panels/lovelace/common/create-badge-element.ts index 2da37939a7ad..9a046cd0a5cc 100644 --- a/src/panels/lovelace/common/create-badge-element.ts +++ b/src/panels/lovelace/common/create-badge-element.ts @@ -8,6 +8,7 @@ import { } from "../badges/hui-error-badge"; import { LovelaceBadge } from "../types"; import { LovelaceBadgeConfig } from "../../../data/lovelace"; +import { fireEvent } from "../../../common/dom/fire_event"; const BADGE_TYPES = new Set(["entity-filter", "error", "state-label"]); const CUSTOM_TYPE_PREFIX = "custom:"; @@ -16,7 +17,7 @@ const TIMEOUT = 2000; const _createElement = ( tag: string, config: LovelaceBadgeConfig -): LovelaceBadge | HuiErrorBadge => { +): LovelaceBadge => { const element = document.createElement(tag) as LovelaceBadge; try { element.setConfig(config); @@ -58,6 +59,7 @@ export const createBadgeElement = ( customElements.whenDefined(tag).then(() => { clearTimeout(timer); + fireEvent(element, "ll-badge-rebuild"); }); return element; diff --git a/src/panels/lovelace/editor/view-editor/hui-edit-view.ts b/src/panels/lovelace/editor/view-editor/hui-edit-view.ts index 6e7ccd28eb44..9d05bef13d99 100644 --- a/src/panels/lovelace/editor/view-editor/hui-edit-view.ts +++ b/src/panels/lovelace/editor/view-editor/hui-edit-view.ts @@ -215,9 +215,9 @@ export class HuiEditView extends LitElement { this._saving = true; const viewConf: LovelaceViewConfig = { - cards: this._cards, - badges: this._badges, ...this._config, + badges: this._badges, + cards: this._cards, }; const lovelace = this.lovelace!; diff --git a/src/panels/lovelace/types.ts b/src/panels/lovelace/types.ts index 85c0c54ed5e7..4557561412bb 100644 --- a/src/panels/lovelace/types.ts +++ b/src/panels/lovelace/types.ts @@ -9,6 +9,7 @@ declare global { // tslint:disable-next-line interface HASSDomEvents { "ll-rebuild": {}; + "ll-badge-rebuild": {}; } } diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index 6fdf97c9d0f3..87f57c319c92 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -11,7 +11,11 @@ import "../../../components/entity/ha-state-label-badge"; import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; -import { LovelaceViewConfig, LovelaceCardConfig } from "../../../data/lovelace"; +import { + LovelaceViewConfig, + LovelaceCardConfig, + LovelaceBadgeConfig, +} from "../../../data/lovelace"; import { HomeAssistant } from "../../../types"; import { classMap } from "lit-html/directives/class-map"; import { Lovelace, LovelaceCard, LovelaceBadge } from "../types"; @@ -86,6 +90,23 @@ export class HUIView extends LitElement { return element; } + public createBadgeElement(badgeConfig: LovelaceBadgeConfig) { + const element = createBadgeElement(badgeConfig) as LovelaceBadge; + element.hass = this.hass; + element.addEventListener( + "ll-badge-rebuild", + (ev) => { + // In edit mode let it go to hui-root and rebuild whole view. + if (!this.lovelace!.editMode) { + ev.stopPropagation(); + this._rebuildBadge(element, badgeConfig); + } + }, + { once: true } + ); + return element; + } + protected render(): TemplateResult | void { return html` ${this.renderStyles()} @@ -338,6 +359,17 @@ export class HUIView extends LitElement { curCardEl === cardElToReplace ? newCardEl : curCardEl ); } + + private _rebuildBadge( + badgeElToReplace: LovelaceBadge, + config: LovelaceBadgeConfig + ): void { + const newBadgeEl = this.createBadgeElement(config); + badgeElToReplace.parentElement!.replaceChild(newBadgeEl, badgeElToReplace); + this._badges = this._cards!.map((curBadgeEl) => + curBadgeEl === badgeElToReplace ? newBadgeEl : curBadgeEl + ); + } } declare global { From 27366545c68203d9e0395d98c47d9f0bbfbf3f27 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Tue, 15 Oct 2019 20:35:43 -0500 Subject: [PATCH 13/16] address comments --- src/panels/lovelace/views/hui-view.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index 87f57c319c92..e0f67dea4541 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -96,11 +96,7 @@ export class HUIView extends LitElement { element.addEventListener( "ll-badge-rebuild", (ev) => { - // In edit mode let it go to hui-root and rebuild whole view. - if (!this.lovelace!.editMode) { - ev.stopPropagation(); - this._rebuildBadge(element, badgeConfig); - } + this._rebuildBadge(element, badgeConfig); }, { once: true } ); From 14734159a282243a69fff74f999cc304cf08c228 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Tue, 15 Oct 2019 20:49:58 -0500 Subject: [PATCH 14/16] fix entity-filter --- src/panels/lovelace/badges/hui-entity-filter-badge.ts | 5 +++-- src/panels/lovelace/views/hui-view.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/panels/lovelace/badges/hui-entity-filter-badge.ts b/src/panels/lovelace/badges/hui-entity-filter-badge.ts index 747f535900c8..eb569aafc9a7 100644 --- a/src/panels/lovelace/badges/hui-entity-filter-badge.ts +++ b/src/panels/lovelace/badges/hui-entity-filter-badge.ts @@ -44,8 +44,6 @@ class EntityFilterBadge extends HTMLElement implements LovelaceBadge { return; } - this._hass = hass; - if (this._elements) { for (const element of this._elements) { element.hass = hass; @@ -53,9 +51,12 @@ class EntityFilterBadge extends HTMLElement implements LovelaceBadge { } if (!this.haveEntitiesChanged(hass)) { + this._hass = hass; return; } + this._hass = hass; + if (!this._configEntities) { this._configEntities = processConfigEntities(this._config.entities); } diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index e0f67dea4541..b6d30f6f03c1 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -95,7 +95,7 @@ export class HUIView extends LitElement { element.hass = this.hass; element.addEventListener( "ll-badge-rebuild", - (ev) => { + () => { this._rebuildBadge(element, badgeConfig); }, { once: true } From 2344e6c5b8f19d5f8a6f619910f66705720d85e6 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Wed, 16 Oct 2019 08:16:50 -0500 Subject: [PATCH 15/16] set hass once --- src/panels/lovelace/views/hui-view.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index b6d30f6f03c1..d7c411f54757 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -278,7 +278,6 @@ export class HUIView extends LitElement { const badges = processConfigEntities(config.badges as any); for (const badge of badges) { const element = createBadgeElement(badge); - element.hass = this.hass; elements.push(element); root.appendChild(element); } From ed5396fae2ef44363280169e998871cd3a1c3932 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Wed, 16 Oct 2019 08:29:21 -0500 Subject: [PATCH 16/16] hass --- src/panels/lovelace/views/hui-view.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/panels/lovelace/views/hui-view.ts b/src/panels/lovelace/views/hui-view.ts index d7c411f54757..b6d30f6f03c1 100644 --- a/src/panels/lovelace/views/hui-view.ts +++ b/src/panels/lovelace/views/hui-view.ts @@ -278,6 +278,7 @@ export class HUIView extends LitElement { const badges = processConfigEntities(config.badges as any); for (const badge of badges) { const element = createBadgeElement(badge); + element.hass = this.hass; elements.push(element); root.appendChild(element); }