From 2758e86fab92bf97fda22cc1f042691e5beb1dd4 Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Fri, 26 Oct 2018 20:24:12 -0500 Subject: [PATCH] Convert hui-icon-element to TypeScript/LitElement and extract ElementClick mixin functions --- src/common/dom/handle-click.ts | 44 ++++++++++++ src/common/string/compute-tooltip.ts | 38 +++++++++++ .../lovelace/common/create-hui-element.js | 2 +- .../lovelace/elements/hui-icon-element.js | 53 --------------- .../lovelace/elements/hui-icon-element.ts | 67 ++++++++++++++++++ src/panels/lovelace/elements/types.ts | 6 ++ .../lovelace/mixins/element-click-mixin.js | 68 ++----------------- 7 files changed, 163 insertions(+), 115 deletions(-) create mode 100644 src/common/dom/handle-click.ts create mode 100644 src/common/string/compute-tooltip.ts delete mode 100644 src/panels/lovelace/elements/hui-icon-element.js create mode 100644 src/panels/lovelace/elements/hui-icon-element.ts diff --git a/src/common/dom/handle-click.ts b/src/common/dom/handle-click.ts new file mode 100644 index 0000000000..284644070a --- /dev/null +++ b/src/common/dom/handle-click.ts @@ -0,0 +1,44 @@ +import { HomeAssistant } from "../../types"; +import { LovelaceElementConfig } from "../../panels/lovelace/elements/types"; +import { fireEvent } from "../dom/fire_event.js"; +import toggleEntity from "../../../src/panels/lovelace/common/entity/toggle-entity"; + +export const handleClick = ( + node: HTMLElement, + hass: HomeAssistant, + config: LovelaceElementConfig, + hold: boolean +): void => { + let action = config.tap_action || "more-info"; + + if (hold && config.hold_action) { + action = config.hold_action; + } + + if (action === "none") { + return; + } + + switch (action) { + case "more-info": + fireEvent(node, "hass-more-info", { entityId: config.entity }); + break; + case "navigate": + // this.navigate(config.navigation_path); // TODO wait for balloob's navigate function + break; + case "toggle": + toggleEntity(hass, config.entity); + break; + case "call-service": { + if (config.service) { + const [domain, service] = config.service.split(".", 2); + const serviceData = Object.assign( + {}, + { entity_id: config.entity }, + config.service_data + ); + hass.callService(domain, service, serviceData); + } + } + } +}; diff --git a/src/common/string/compute-tooltip.ts b/src/common/string/compute-tooltip.ts new file mode 100644 index 0000000000..4346e97234 --- /dev/null +++ b/src/common/string/compute-tooltip.ts @@ -0,0 +1,38 @@ +import computeStateName from "../../common/entity/compute_state_name"; +import { HomeAssistant } from "../../types"; +import { LovelaceElementConfig } from "../../panels/lovelace/elements/types"; + +export const computeTooltip = ( + hass: HomeAssistant, + config: LovelaceElementConfig +): string => { + if (config.title) { + return config.title; + } + + let stateName = ""; + let tooltip: string; + + if (config.entity) { + stateName = + config.entity in hass.states + ? computeStateName(hass.states[config.entity]) + : config.entity; + } + + switch (config.tap_action) { + case "navigate": + tooltip = `Navigate to ${config.navigation_path}`; + break; + case "toggle": + tooltip = `Toggle ${stateName}`; + break; + case "call-service": + tooltip = `Call service ${config.service}`; + break; + default: + tooltip = `Show more-info: ${stateName}`; + } + + return tooltip; +}; diff --git a/src/panels/lovelace/common/create-hui-element.js b/src/panels/lovelace/common/create-hui-element.js index e74985ca13..8394c12115 100644 --- a/src/panels/lovelace/common/create-hui-element.js +++ b/src/panels/lovelace/common/create-hui-element.js @@ -1,4 +1,4 @@ -import "../elements/hui-icon-element.js"; +import "../elements/hui-icon-element"; import "../elements/hui-image-element.js"; import "../elements/hui-service-button-element.js"; import "../elements/hui-state-badge-element.js"; diff --git a/src/panels/lovelace/elements/hui-icon-element.js b/src/panels/lovelace/elements/hui-icon-element.js deleted file mode 100644 index 5eb2bb2631..0000000000 --- a/src/panels/lovelace/elements/hui-icon-element.js +++ /dev/null @@ -1,53 +0,0 @@ -import { html } from "@polymer/polymer/lib/utils/html-tag.js"; -import { PolymerElement } from "@polymer/polymer/polymer-element.js"; - -import "../../../components/ha-icon.js"; - -import ElementClickMixin from "../mixins/element-click-mixin.js"; -import { longPressBind } from "../common/directives/long-press-directive"; - -/* - * @appliesMixin ElementClickMixin - */ -class HuiIconElement extends ElementClickMixin(PolymerElement) { - static get template() { - return html` - - - `; - } - - static get properties() { - return { - hass: Object, - _config: Object, - }; - } - - ready() { - super.ready(); - longPressBind(this); - this.addEventListener("ha-click", () => - this.handleClick(this.hass, this._config, false) - ); - this.addEventListener("ha-hold", () => - this.handleClick(this.hass, this._config, true) - ); - } - - setConfig(config) { - if (!config || !config.icon) { - throw Error("Error in element configuration"); - } - - this._config = config; - } -} -customElements.define("hui-icon-element", HuiIconElement); diff --git a/src/panels/lovelace/elements/hui-icon-element.ts b/src/panels/lovelace/elements/hui-icon-element.ts new file mode 100644 index 0000000000..8fc4236c01 --- /dev/null +++ b/src/panels/lovelace/elements/hui-icon-element.ts @@ -0,0 +1,67 @@ +import { html, LitElement } from "@polymer/lit-element"; + +import "../../../components/ha-icon.js"; + +import { computeTooltip } from "../../../common/string/compute-tooltip"; +import { handleClick } from "../../../common/dom/handle-click"; +import { longPress } from "../common/directives/long-press-directive"; +import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin"; +import { LovelaceElement, LovelaceElementConfig } from "./types.js"; +import { HomeAssistant } from "../../../types.js"; + +interface Config extends LovelaceElementConfig { + icon: string; +} + +export class HuiIconElement extends hassLocalizeLitMixin(LitElement) + implements LovelaceElement { + public hass?: HomeAssistant; + private _config?: Config; + + static get properties() { + return { hass: {}, _config: {} }; + } + + public setConfig(config: Config) { + if (!config.icon) { + throw Error("Invalid Configuration: 'icon' required"); + } + + this._config = config; + } + + protected render() { + if (!this._config) { + return html``; + } + + return html` + ${this.renderStyle()} + + `; + } + + private renderStyle() { + return html` + + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-icon-element": HuiIconElement; + } +} + +customElements.define("hui-icon-element", HuiIconElement); diff --git a/src/panels/lovelace/elements/types.ts b/src/panels/lovelace/elements/types.ts index 7b8b2c59cd..71407adf19 100644 --- a/src/panels/lovelace/elements/types.ts +++ b/src/panels/lovelace/elements/types.ts @@ -4,6 +4,12 @@ export interface LovelaceElementConfig { type: string; entity?: string; style: object; + tap_action?: string; + navigation_path?: string; + service?: string; + title?: string; + hold_action?: string; + service_data?: object; } export interface LovelaceElement extends HTMLElement { diff --git a/src/panels/lovelace/mixins/element-click-mixin.js b/src/panels/lovelace/mixins/element-click-mixin.js index 02a7cdb9fd..0832139f0f 100644 --- a/src/panels/lovelace/mixins/element-click-mixin.js +++ b/src/panels/lovelace/mixins/element-click-mixin.js @@ -1,70 +1,16 @@ import { dedupingMixin } from "@polymer/polymer/lib/utils/mixin.js"; -import toggleEntity from "../common/entity/toggle-entity.js"; -import NavigateMixin from "../../../mixins/navigate-mixin"; -import EventsMixin from "../../../mixins/events-mixin.js"; -import computeStateName from "../../../common/entity/compute_state_name"; +import { computeTooltip } from "../../../common/string/compute-tooltip"; +import { handleClick } from "../../../common/dom/handle-click"; -/* - * @polymerMixin - * @appliesMixin EventsMixin - * @appliesMixin NavigateMixin - */ export default dedupingMixin( (superClass) => - class extends NavigateMixin(EventsMixin(superClass)) { - handleClick(hass, config, hold) { - let action = config.tap_action || "more-info"; - if (hold) { - action = config.hold_action; - } - if (action === "none") return; - - switch (action) { - case "more-info": - this.fire("hass-more-info", { entityId: config.entity }); - break; - case "navigate": - this.navigate(config.navigation_path); - break; - case "toggle": - toggleEntity(hass, config.entity); - break; - case "call-service": { - const [domain, service] = config.service.split(".", 2); - const serviceData = Object.assign( - {}, - { entity_id: config.entity }, - config.service_data - ); - hass.callService(domain, service, serviceData); - } - } + class extends superClass { + handleClick(...args) { + handleClick(this, ...args); } - computeTooltip(hass, config) { - if (config.title) return config.title; - - const stateName = - config.entity in hass.states - ? computeStateName(hass.states[config.entity]) - : config.entity; - - let tooltip; - switch (config.tap_action) { - case "navigate": - tooltip = `Navigate to ${config.navigation_path}`; - break; - case "toggle": - tooltip = `Toggle ${stateName}`; - break; - case "call-service": - tooltip = `Call service ${config.service}`; - break; - default: - tooltip = `Show more-info: ${stateName}`; - } - - return tooltip; + computeTooltip(...args) { + computeTooltip(...args); } } );