From 18be134ad8ec8567bbebc0ee1b552450c2285a41 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Wed, 17 Oct 2018 09:55:30 -0400 Subject: [PATCH] Updating Entities Card to TS+lit --- .../lovelace/cards/hui-entities-card.js | 150 -------------- .../lovelace/cards/hui-entities-card.ts | 194 ++++++++++++++++++ .../lovelace/common/create-card-element.js | 2 +- src/panels/lovelace/hui-unused-entities.js | 2 +- 4 files changed, 196 insertions(+), 152 deletions(-) delete mode 100644 src/panels/lovelace/cards/hui-entities-card.js create mode 100644 src/panels/lovelace/cards/hui-entities-card.ts diff --git a/src/panels/lovelace/cards/hui-entities-card.js b/src/panels/lovelace/cards/hui-entities-card.js deleted file mode 100644 index 85e89af5f3..0000000000 --- a/src/panels/lovelace/cards/hui-entities-card.js +++ /dev/null @@ -1,150 +0,0 @@ -import "@polymer/iron-flex-layout/iron-flex-layout-classes.js"; -import { html } from "@polymer/polymer/lib/utils/html-tag.js"; -import { PolymerElement } from "@polymer/polymer/polymer-element.js"; - -import "../../../components/ha-card.js"; -import "../components/hui-entities-toggle.js"; - -import createRowElement from "../common/create-row-element.js"; -import computeDomain from "../../../common/entity/compute_domain.js"; -import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const.js"; - -import EventsMixin from "../../../mixins/events-mixin.js"; - -/* - * @appliesMixin EventsMixin - */ -class HuiEntitiesCard extends EventsMixin(PolymerElement) { - static get template() { - return html` - - - - -
-
-`; - } - - static get properties() { - return { - hass: { - type: Object, - observer: "_hassChanged", - }, - _config: Object, - }; - } - - constructor() { - super(); - this._elements = []; - } - - ready() { - super.ready(); - if (this._config) this._buildConfig(); - } - - getCardSize() { - // +1 for the header - return 1 + (this._config ? this._config.entities.length : 0); - } - - _showHeaderToggle(show) { - // If show is undefined, we treat it as true - return show !== false; - } - - _showHeader(config) { - // Show header if either title or toggle configured to show in it - return config.title || config.show_header_toggle; - } - - setConfig(config) { - this._config = config; - this._rows = config.entities.map( - (item) => (typeof item === "string" ? { entity: item } : item) - ); - if (this.$) this._buildConfig(); - } - - _buildConfig() { - const root = this.$.states; - - while (root.lastChild) { - root.removeChild(root.lastChild); - } - - this._elements = []; - - for (const row of this._rows) { - const entityId = row.entity; - const element = createRowElement(row); - if ( - entityId && - !DOMAINS_HIDE_MORE_INFO.includes(computeDomain(entityId)) - ) { - element.classList.add("state-card-dialog"); - element.addEventListener("click", () => - this.fire("hass-more-info", { entityId }) - ); - } - element.hass = this.hass; - this._elements.push(element); - const container = document.createElement("div"); - container.appendChild(element); - root.appendChild(container); - } - } - - _hassChanged(hass) { - this._elements.forEach((element) => { - element.hass = hass; - }); - } - - _filterEntities(items) { - return items - .filter((item) => typeof item === "string" || item.entity) - .map((item) => (typeof item === "string" ? item : item.entity)); - } -} - -customElements.define("hui-entities-card", HuiEntitiesCard); diff --git a/src/panels/lovelace/cards/hui-entities-card.ts b/src/panels/lovelace/cards/hui-entities-card.ts new file mode 100644 index 0000000000..d0af91aebf --- /dev/null +++ b/src/panels/lovelace/cards/hui-entities-card.ts @@ -0,0 +1,194 @@ +import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element"; +import { repeat } from "lit-html/directives/repeat"; + +import "../../../components/ha-card.js"; +import "../components/hui-entities-toggle.js"; + +import { fireEvent } from "../../../common/dom/fire_event.js"; +import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const.js"; +import { HassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin"; +import { LovelaceCard, LovelaceConfig } from "../types.js"; +import { HomeAssistant } from "../../../types.js"; +import createRowElement from "../common/create-row-element.js"; +import computeDomain from "../../../common/entity/compute_domain.js"; +import processConfigEntities from "../common/process-config-entities"; + +interface EntityConfig { + name?: string; + icon?: string; + entity: string; + type?: string; + secondary_info: "entity-id" | "last-changed"; + action_name?: string; + service?: string; + service_data?: object; + url?: string; +} + +interface Config extends LovelaceConfig { + show_header_toggle?: boolean; + title?: string; + entities: EntityConfig[]; +} + +class HuiEntitiesCard extends HassLocalizeLitMixin(LitElement) + implements LovelaceCard { + protected hass?: HomeAssistant; + protected config?: Config; + protected configEntities?: EntityConfig[]; + + static get properties(): PropertyDeclarations { + return { + hass: {}, + config: {}, + }; + } + + public getCardSize() { + // +1 for the header + return 1 + (this.config ? this.config.entities.length : 0); + } + + public setConfig(config: Config) { + this.config = { show_header_toggle: true, ...config }; + const entities = processConfigEntities(config.entities); + + for (const entity of entities) { + if ( + entity.type === "call-service" && + !entity.service && + !entity.name && + !entity.icon && + !entity.service_data && + !entity.action_name + ) { + throw new Error("Missing required property when type is call-service"); + } else if ( + entity.type === "weblink" && + !entity.name && + !entity.icon && + !entity.url + ) { + throw new Error("Missing required property when type is weblink"); + } + } + + this.configEntities = entities; + if (this.hass) { + this.requestUpdate(); + } + } + + protected render() { + if (!this.config || !this.hass) { + return html``; + } + const { show_header_toggle, title } = this.config; + const states = this.hass.states; + + const stateEntities = this.configEntities!.filter( + (conf) => conf.entity in states + ); + + const rowEntities = this.configEntities!.filter( + (item) => typeof item === "string" || item.entity + ).map((item) => (typeof item === "string" ? item : item.entity)); + + return html` + ${this.renderStyle()} + + ${ + !title && !show_header_toggle + ? html`` + : html` +
+ ${!title ? html`` : html`
${title}
`} + ${ + !show_header_toggle + ? html`` + : html` + + ` + } +
` + } +
+ ${repeat( + stateEntities, + (entityConf) => entityConf.entity, + (entityConf) => this.renderEntity(entityConf) + )} +
+
+ `; + } + + private renderStyle() { + return html` + + `; + } + + private renderEntity(entityConf) { + const element = createRowElement(entityConf); + element.hass = this.hass; + element.entityConf = entityConf; + if (!DOMAINS_HIDE_MORE_INFO.includes(computeDomain(entityConf.entity))) { + element.classList.add("state-card-dialog"); + element.onclick = this.handleClick; + } + + return html` +
+ ${element} +
+ `; + } + + private handleClick(ev: MouseEvent) { + const config = (ev.currentTarget as any).entityConf as EntityConfig; + const entityId = config.entity; + + fireEvent(this, "hass-more-info", { entityId }); + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-entities-card": HuiEntitiesCard; + } +} + +customElements.define("hui-entities-card", HuiEntitiesCard); diff --git a/src/panels/lovelace/common/create-card-element.js b/src/panels/lovelace/common/create-card-element.js index 73ee2bf8af..c7d1a876ee 100644 --- a/src/panels/lovelace/common/create-card-element.js +++ b/src/panels/lovelace/common/create-card-element.js @@ -2,7 +2,7 @@ import { fireEvent } from "../../../common/dom/fire_event.js"; import "../cards/hui-alarm-panel-card.js"; import "../cards/hui-conditional-card.ts"; -import "../cards/hui-entities-card.js"; +import "../cards/hui-entities-card.ts"; import "../cards/hui-entity-button-card.ts"; import "../cards/hui-entity-filter-card.js"; import "../cards/hui-error-card.js"; diff --git a/src/panels/lovelace/hui-unused-entities.js b/src/panels/lovelace/hui-unused-entities.js index 196d464b48..9b9e318954 100644 --- a/src/panels/lovelace/hui-unused-entities.js +++ b/src/panels/lovelace/hui-unused-entities.js @@ -4,7 +4,7 @@ import { PolymerElement } from "@polymer/polymer/polymer-element.js"; import computeUnusedEntities from "./common/compute-unused-entities.js"; import createCardElement from "./common/create-card-element.js"; -import "./cards/hui-entities-card.js"; +import "./cards/hui-entities-card.ts"; class HuiUnusedEntities extends PolymerElement { static get template() {