From de3a4676974518e1cbd32c76d41ccd9349de6e8c Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Wed, 5 Dec 2018 08:27:22 -0500 Subject: [PATCH] Update Hold/Tap Actions to Objects (#2182) * Update Action to Object for entity-button * Update Actions to Object for Glance Card * Update to use HandleClick function * Add navigation * Updating to use navigation path from Action Config * Type handle events in glance * Update Service checks * Update Picture elements * oops * Adding nav back until we convert picture * Extend typing --- src/data/lovelace.ts | 30 ++++++++++++ .../lovelace/cards/hui-entity-button-card.ts | 49 +++++-------------- src/panels/lovelace/cards/hui-glance-card.ts | 48 +++++++----------- .../lovelace/cards/hui-picture-entity-card.ts | 12 ++--- src/panels/lovelace/common/compute-tooltip.ts | 2 +- src/panels/lovelace/common/handle-click.ts | 42 +++++++++------- .../lovelace/elements/hui-icon-element.ts | 12 ++++- .../lovelace/elements/hui-image-element.ts | 9 ++-- .../elements/hui-state-label-element.ts | 12 ++++- src/panels/lovelace/elements/types.ts | 7 +-- 10 files changed, 122 insertions(+), 101 deletions(-) diff --git a/src/data/lovelace.ts b/src/data/lovelace.ts index c731360321..cd806b682b 100644 --- a/src/data/lovelace.ts +++ b/src/data/lovelace.ts @@ -21,6 +21,36 @@ export interface LovelaceCardConfig { [key: string]: any; } +export interface ToggleActionConfig { + action: "toggle"; +} + +export interface CallServiceActionConfig { + action: "call-service"; + service: string; + service_data?: { [key: string]: any }; +} + +export interface NavigateActionConfig { + action: "navigate"; + navigation_path: string; +} + +export interface MoreInfoActionConfig { + action: "more-info"; +} + +export interface NoActionConfig { + action: "none"; +} + +export type ActionConfig = + | ToggleActionConfig + | CallServiceActionConfig + | NavigateActionConfig + | MoreInfoActionConfig + | NoActionConfig; + export const fetchConfig = (hass: HomeAssistant): Promise => hass.callWS({ type: "lovelace/config", diff --git a/src/panels/lovelace/cards/hui-entity-button-card.ts b/src/panels/lovelace/cards/hui-entity-button-card.ts index 4bc9d08e5d..fbb074b0b4 100644 --- a/src/panels/lovelace/cards/hui-entity-button-card.ts +++ b/src/panels/lovelace/cards/hui-entity-button-card.ts @@ -15,23 +15,20 @@ import stateIcon from "../../../common/entity/state_icon"; import computeStateDomain from "../../../common/entity/compute_state_domain"; import computeStateName from "../../../common/entity/compute_state_name"; import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; -import { toggleEntity } from "../common/entity/toggle-entity"; import { HomeAssistant, LightEntity } from "../../../types"; import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin"; import { LovelaceCard } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; +import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace"; import { longPress } from "../common/directives/long-press-directive"; -import { fireEvent } from "../../../common/dom/fire_event"; +import { handleClick } from "../common/handle-click"; interface Config extends LovelaceCardConfig { entity: string; name?: string; icon?: string; theme?: string; - tap_action?: "toggle" | "call-service" | "more-info"; - hold_action?: "toggle" | "call-service" | "more-info"; - service?: string; - service_data?: object; + tap_action?: ActionConfig; + hold_action?: ActionConfig; } class HuiEntityButtonCard extends hassLocalizeLitMixin(LitElement) @@ -82,8 +79,8 @@ class HuiEntityButtonCard extends hassLocalizeLitMixin(LitElement) return html` ${this.renderStyle()} ${ @@ -187,34 +184,12 @@ class HuiEntityButtonCard extends hassLocalizeLitMixin(LitElement) return `hsl(${hue}, 100%, ${100 - sat / 2}%)`; } - private handleClick(hold: boolean): void { - const config = this._config; - if (!config) { - return; - } - const stateObj = this.hass!.states[config.entity]; - if (!stateObj) { - return; - } - const entityId = stateObj.entity_id; - const action = hold ? config.hold_action : config.tap_action || "more-info"; - switch (action) { - case "toggle": - toggleEntity(this.hass!, entityId); - break; - case "call-service": - if (!config.service) { - return; - } - const [domain, service] = config.service.split(".", 2); - const serviceData = { entity_id: entityId, ...config.service_data }; - this.hass!.callService(domain, service, serviceData); - break; - case "more-info": - fireEvent(this, "hass-more-info", { entityId }); - break; - default: - } + private _handleTap() { + handleClick(this, this.hass!, this._config!, false); + } + + private _handleHold() { + handleClick(this, this.hass!, this._config!, true); } } diff --git a/src/panels/lovelace/cards/hui-glance-card.ts b/src/panels/lovelace/cards/hui-glance-card.ts index b342c15ddf..ff74e0dc0f 100644 --- a/src/panels/lovelace/cards/hui-glance-card.ts +++ b/src/panels/lovelace/cards/hui-glance-card.ts @@ -7,14 +7,12 @@ import { import { TemplateResult } from "lit-html"; import { classMap } from "lit-html/directives/classMap"; -import { fireEvent } from "../../../common/dom/fire_event"; import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin"; import { HomeAssistant } from "../../../types"; import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; +import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace"; import { longPress } from "../common/directives/long-press-directive"; import { EntityConfig } from "../entity-rows/types"; -import { toggleEntity } from "../common/entity/toggle-entity"; import { processConfigEntities } from "../common/process-config-entities"; import computeStateDisplay from "../../../common/entity/compute_state_display"; @@ -24,12 +22,11 @@ import applyThemesOnElement from "../../../common/dom/apply_themes_on_element"; import "../../../components/entity/state-badge"; import "../../../components/ha-card"; import "../../../components/ha-icon"; +import { handleClick } from "../common/handle-click"; export interface ConfigEntity extends EntityConfig { - tap_action?: "toggle" | "call-service" | "more-info"; - hold_action?: "toggle" | "call-service" | "more-info"; - service?: string; - service_data?: object; + tap_action?: ActionConfig; + hold_action?: ActionConfig; } export interface Config extends LovelaceCardConfig { @@ -75,9 +72,12 @@ export class HuiGlanceCard extends hassLocalizeLitMixin(LitElement) for (const entity of entities) { if ( - (entity.tap_action === "call-service" || - entity.hold_action === "call-service") && - !entity.service + (entity.tap_action && + entity.tap_action.action === "call-service" && + !entity.tap_action.service) || + (entity.hold_action && + entity.hold_action.action === "call-service" && + !entity.hold_action.service) ) { throw new Error( 'Missing required property "service" when tap_action or hold_action is call-service' @@ -203,8 +203,8 @@ export class HuiGlanceCard extends hassLocalizeLitMixin(LitElement)
${ @@ -243,24 +243,14 @@ export class HuiGlanceCard extends hassLocalizeLitMixin(LitElement) `; } - private handleClick(ev: MouseEvent, hold: boolean): void { + private _handleTap(ev: MouseEvent) { const config = (ev.currentTarget as any).entityConf as ConfigEntity; - const entityId = config.entity; - const action = hold ? config.hold_action : config.tap_action || "more-info"; - switch (action) { - case "toggle": - toggleEntity(this.hass!, entityId); - break; - case "call-service": - const [domain, service] = config.service!.split(".", 2); - const serviceData = { entity_id: entityId, ...config.service_data }; - this.hass!.callService(domain, service, serviceData); - break; - case "more-info": - fireEvent(this, "hass-more-info", { entityId }); - break; - default: - } + handleClick(this, this.hass!, config, false); + } + + private _handleHold(ev: MouseEvent) { + const config = (ev.currentTarget as any).entityConf as ConfigEntity; + handleClick(this, this.hass!, config, true); } } diff --git a/src/panels/lovelace/cards/hui-picture-entity-card.ts b/src/panels/lovelace/cards/hui-picture-entity-card.ts index 8c2e1cde12..64580368e7 100644 --- a/src/panels/lovelace/cards/hui-picture-entity-card.ts +++ b/src/panels/lovelace/cards/hui-picture-entity-card.ts @@ -12,7 +12,7 @@ import computeStateName from "../../../common/entity/compute_state_name"; import { longPress } from "../common/directives/long-press-directive"; import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin"; import { HomeAssistant } from "../../../types"; -import { LovelaceCardConfig } from "../../../data/lovelace"; +import { LovelaceCardConfig, ActionConfig } from "../../../data/lovelace"; import { LovelaceCard } from "../types"; import { handleClick } from "../common/handle-click"; import { UNAVAILABLE } from "../../../data/entity"; @@ -25,10 +25,8 @@ interface Config extends LovelaceCardConfig { camera_image?: string; state_image?: {}; aspect_ratio?: string; - tap_action?: "toggle" | "call-service" | "more-info" | "navigate"; - hold_action?: "toggle" | "call-service" | "more-info" | "navigate"; - service?: string; - service_data?: object; + tap_action?: ActionConfig; + hold_action?: ActionConfig; show_name?: boolean; show_state?: boolean; } @@ -109,7 +107,7 @@ class HuiPictureEntityCard extends hassLocalizeLitMixin(LitElement) }" .entity="${this._config.entity}" .aspectRatio="${this._config.aspect_ratio}" - @ha-click="${this._handleClick}" + @ha-click="${this._handleTap}" @ha-hold="${this._handleHold}" .longPress="${longPress()}" class="${ @@ -157,7 +155,7 @@ class HuiPictureEntityCard extends hassLocalizeLitMixin(LitElement) `; } - private _handleClick() { + private _handleTap() { handleClick(this, this.hass!, this._config!, false); } diff --git a/src/panels/lovelace/common/compute-tooltip.ts b/src/panels/lovelace/common/compute-tooltip.ts index 59920ec8e1..7ab9830223 100644 --- a/src/panels/lovelace/common/compute-tooltip.ts +++ b/src/panels/lovelace/common/compute-tooltip.ts @@ -20,7 +20,7 @@ export const computeTooltip = ( : config.entity; } - switch (config.tap_action) { + switch (config.tap_action && config.tap_action.action) { case "navigate": tooltip = `Navigate to ${config.navigation_path}`; break; diff --git a/src/panels/lovelace/common/handle-click.ts b/src/panels/lovelace/common/handle-click.ts index f6f654f744..ba463d2025 100644 --- a/src/panels/lovelace/common/handle-click.ts +++ b/src/panels/lovelace/common/handle-click.ts @@ -1,47 +1,55 @@ import { HomeAssistant } from "../../../types"; -import { LovelaceElementConfig } from "../elements/types"; import { fireEvent } from "../../../common/dom/fire_event"; import { navigate } from "../../../common/navigate"; import { toggleEntity } from "../../../../src/panels/lovelace/common/entity/toggle-entity"; -import { LovelaceCardConfig } from "../../../data/lovelace"; +import { ActionConfig } from "../../../data/lovelace"; export const handleClick = ( node: HTMLElement, hass: HomeAssistant, - config: LovelaceElementConfig | LovelaceCardConfig, + config: { + entity?: string; + hold_action?: ActionConfig; + tap_action?: ActionConfig; + }, hold: boolean ): void => { - let action = config.tap_action || "more-info"; + let actionConfig: ActionConfig | undefined; if (hold && config.hold_action) { - action = config.hold_action; + actionConfig = config.hold_action; + } else if (!hold && config.tap_action) { + actionConfig = config.tap_action; } - if (action === "none") { - return; + if (!actionConfig) { + actionConfig = { + action: "more-info", + }; } - switch (action) { + switch (actionConfig.action) { case "more-info": if (config.entity) { fireEvent(node, "hass-more-info", { entityId: config.entity }); } break; case "navigate": - navigate(node, config.navigation_path ? config.navigation_path : ""); + if (actionConfig.navigation_path) { + navigate(node, actionConfig.navigation_path); + } break; case "toggle": - toggleEntity(hass, config.entity!); + if (config.entity) { + toggleEntity(hass, config.entity!); + } break; case "call-service": { - if (config.service) { - const [domain, service] = config.service.split(".", 2); - const serviceData = { - entity_id: config.entity, - ...config.service_data, - }; - hass.callService(domain, service, serviceData); + if (!actionConfig.service) { + return; } + const [domain, service] = actionConfig.service.split(".", 2); + hass.callService(domain, service, actionConfig.service_data); } } }; diff --git a/src/panels/lovelace/elements/hui-icon-element.ts b/src/panels/lovelace/elements/hui-icon-element.ts index ea45b16ba0..ee398c3c84 100644 --- a/src/panels/lovelace/elements/hui-icon-element.ts +++ b/src/panels/lovelace/elements/hui-icon-element.ts @@ -41,13 +41,21 @@ export class HuiIconElement extends hassLocalizeLitMixin(LitElement) `; } + private _handleTap() { + handleClick(this, this.hass!, this._config!, false); + } + + private _handleHold() { + handleClick(this, this.hass!, this._config!, true); + } + private renderStyle(): TemplateResult { return html`