Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/data/lovelace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<LovelaceConfig> =>
hass.callWS({
type: "lovelace/config",
Expand Down
49 changes: 12 additions & 37 deletions src/panels/lovelace/cards/hui-entity-button-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -82,8 +79,8 @@ class HuiEntityButtonCard extends hassLocalizeLitMixin(LitElement)
return html`
${this.renderStyle()}
<ha-card
@ha-click="${() => this.handleClick(false)}"
@ha-hold="${() => this.handleClick(true)}"
@ha-click="${this._handleTap}"
@ha-hold="${this._handleHold}"
.longPress="${longPress()}"
>
${
Expand Down Expand Up @@ -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);
}
}

Expand Down
48 changes: 19 additions & 29 deletions src/panels/lovelace/cards/hui-glance-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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 {
Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -203,8 +203,8 @@ export class HuiGlanceCard extends hassLocalizeLitMixin(LitElement)
<div
class="entity"
.entityConf="${entityConf}"
@ha-click="${(ev) => this.handleClick(ev, false)}"
@ha-hold="${(ev) => this.handleClick(ev, true)}"
@ha-click="${this._handleTap}"
@ha-hold="${this._handleHold}"
.longPress="${longPress()}"
>
${
Expand Down Expand Up @@ -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);
}
}

Expand Down
12 changes: 5 additions & 7 deletions src/panels/lovelace/cards/hui-picture-entity-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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;
}
Expand Down Expand Up @@ -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="${
Expand Down Expand Up @@ -157,7 +155,7 @@ class HuiPictureEntityCard extends hassLocalizeLitMixin(LitElement)
`;
}

private _handleClick() {
private _handleTap() {
handleClick(this, this.hass!, this._config!, false);
}

Expand Down
2 changes: 1 addition & 1 deletion src/panels/lovelace/common/compute-tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
42 changes: 25 additions & 17 deletions src/panels/lovelace/common/handle-click.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
};
12 changes: 10 additions & 2 deletions src/panels/lovelace/elements/hui-icon-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,21 @@ export class HuiIconElement extends hassLocalizeLitMixin(LitElement)
<ha-icon
.icon="${this._config.icon}"
.title="${computeTooltip(this.hass!, this._config)}"
@ha-click="${() => handleClick(this, this.hass!, this._config!, false)}"
@ha-hold="${() => handleClick(this, this.hass!, this._config!, true)}"
@ha-click="${this._handleTap}"
@ha-hold="${this._handleHold}"
.longPress="${longPress()}"
></ha-icon>
`;
}

private _handleTap() {
handleClick(this, this.hass!, this._config!, false);
}

private _handleHold() {
handleClick(this, this.hass!, this._config!, true);
}

private renderStyle(): TemplateResult {
return html`
<style>
Expand Down
9 changes: 6 additions & 3 deletions src/panels/lovelace/elements/hui-image-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ export class HuiImageElement extends hassLocalizeLitMixin(LitElement)
throw Error("Error in element configuration");
}

this.classList.toggle("clickable", config.tap_action !== "none");
this.classList.toggle(
"clickable",
config.tap_action && config.tap_action.action !== "none"
);
this._config = config;
}

Expand All @@ -54,7 +57,7 @@ export class HuiImageElement extends hassLocalizeLitMixin(LitElement)
.stateFilter="${this._config.state_filter}"
.title="${computeTooltip(this.hass!, this._config)}"
.aspectRatio="${this._config.aspect_ratio}"
@ha-click="${this._handleClick}"
@ha-click="${this._handleTap}"
@ha-hold="${this._handleHold}"
.longPress="${longPress()}"
></hui-image>
Expand All @@ -76,7 +79,7 @@ export class HuiImageElement extends hassLocalizeLitMixin(LitElement)
`;
}

private _handleClick() {
private _handleTap() {
handleClick(this, this.hass!, this._config!, false);
}

Expand Down
Loading