Skip to content

Commit 25c76f7

Browse files
committed
feat(#105): custom tap_action per entity
1 parent 32f994c commit 25c76f7

File tree

5 files changed

+164
-204
lines changed

5 files changed

+164
-204
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ This card is intended to display connections between entities with numeric state
6363
| color_above | string | **Optional** | var(--paper-item-icon-color)| Color for state value above color_limit
6464
| color_below | string | **Optional** | var(--primary-color)| Color for state value below color_limit
6565
| add_entities | list | **Optional** | | Experimental. List of entity ids. Their states will be added to this entity, showing a sum.
66-
| subtract_entities| list | **Optional** | | Experimental. List of entity ids. Their states will be subtracted from this entity's state
66+
| subtract_entities | list | **Optional** | | Experimental. List of entity ids. Their states will be subtracted from this entity's state
67+
| tap_action | action | **Optional** | more-info | Home assistant action to perform on tap. Supported actions are `more-info`, `navigate`, `url`, `toggle`, `call-service`, `fire-dom-event`
6768

6869
### Entity types
6970

@@ -171,7 +172,9 @@ This card supports automatic configuration generation based on the HA energy das
171172
- sensor.washer
172173
- entity_id: sensor.floor2
173174
- entities:
174-
- sensor.ev_charger
175+
- entity_id: sensor.ev_charger
176+
tap_action:
177+
action: toggle
175178
- entity_id: garage_other
176179
type: remaining_parent_state
177180
name: Other

src/action-handler-directive.ts

Lines changed: 0 additions & 198 deletions
This file was deleted.

src/chart.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@ import { LitElement, html, svg, TemplateResult, SVGTemplateResult, PropertyValue
22
import { styleMap } from 'lit/directives/style-map';
33
import { classMap } from 'lit/directives/class-map';
44
import { until } from 'lit/directives/until.js';
5+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
56
import { customElement, property, state } from 'lit/decorators';
6-
import { HomeAssistant, stateIcon, fireEvent } from 'custom-card-helpers'; // This is a community maintained npm module with common helper functions/types. https://github.com/custom-cards/custom-card-helpers
7+
import { HomeAssistant, stateIcon } from 'custom-card-helpers'; // This is a community maintained npm module with common helper functions/types. https://github.com/custom-cards/custom-card-helpers
78

89
import type { Config, SectionState, Box, ConnectionState, EntityConfigInternal, NormalizedState } from './types';
910
import { MIN_LABEL_HEIGHT } from './const';
1011
import { localize } from './localize/localize';
1112
import styles from './styles';
1213
import { formatState, getChildConnections, getEntityId, normalizeStateValue, renderError } from './utils';
1314
import { HassEntities, HassEntity } from 'home-assistant-js-websocket';
15+
import { handleAction } from './handle-actions';
1416

1517
@customElement('sankey-chart-base')
1618
export class Chart extends LitElement {
@@ -378,7 +380,7 @@ export class Chart extends LitElement {
378380
}
379381

380382
private _handleBoxClick(box: Box): void {
381-
fireEvent(this, 'hass-more-info', { entityId: box.entity_id });
383+
handleAction(this, this.hass, box.config, 'tap');
382384
}
383385

384386
private _handleMouseEnter(box: Box): void {

src/handle-actions.ts

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import { HomeAssistant, fireEvent, forwardHaptic, navigate, toggleEntity } from "custom-card-helpers";
2+
import { ActionConfigExtended } from "./types";
3+
4+
interface ToastActionParams {
5+
action: () => void;
6+
text: string;
7+
}
8+
interface ShowToastParams {
9+
message: string;
10+
action?: ToastActionParams;
11+
duration?: number;
12+
dismissable?: boolean;
13+
}
14+
const showToast = (el: HTMLElement, params: ShowToastParams) =>
15+
fireEvent(el, "hass-notification", params);
16+
17+
export const handleAction = async (
18+
node: HTMLElement,
19+
hass: HomeAssistant,
20+
config: {
21+
entity_id: string;
22+
hold_action?: ActionConfigExtended;
23+
tap_action?: ActionConfigExtended;
24+
double_tap_action?: ActionConfigExtended;
25+
},
26+
action: string
27+
): Promise<void> => {
28+
let actionConfig = config.tap_action;
29+
30+
if (action === "double_tap" && config.double_tap_action) {
31+
actionConfig = config.double_tap_action;
32+
} else if (action === "hold" && config.hold_action) {
33+
actionConfig = config.hold_action;
34+
}
35+
36+
if (!actionConfig) {
37+
actionConfig = {
38+
action: "more-info",
39+
};
40+
}
41+
42+
if (
43+
actionConfig.confirmation &&
44+
(!actionConfig.confirmation.exemptions ||
45+
!actionConfig.confirmation.exemptions.some((e) => e.user === hass!.user!.id))
46+
) {
47+
forwardHaptic("warning");
48+
49+
if (
50+
!confirm(
51+
actionConfig.confirmation.text ||
52+
hass.localize(
53+
"ui.panel.lovelace.cards.actions.action_confirmation",
54+
"action",
55+
hass.localize(
56+
"ui.panel.lovelace.editor.action-editor.actions." +
57+
actionConfig.action
58+
) ||
59+
actionConfig.action
60+
)
61+
)
62+
) {
63+
return;
64+
}
65+
}
66+
67+
switch (actionConfig.action) {
68+
case "more-info": {
69+
fireEvent(node, "hass-more-info", {
70+
// @ts-ignore
71+
entityId: actionConfig.entity ?? actionConfig.data?.entity_id ?? config.entity_id,
72+
});
73+
break;
74+
}
75+
case "navigate":
76+
if (actionConfig.navigation_path) {
77+
navigate(node, actionConfig.navigation_path);
78+
} else {
79+
showToast(node, {
80+
message: hass.localize("ui.panel.lovelace.cards.actions.no_navigation_path"),
81+
});
82+
forwardHaptic("failure");
83+
}
84+
break;
85+
case "url": {
86+
if (actionConfig.url_path) {
87+
window.open(actionConfig.url_path);
88+
} else {
89+
showToast(node, {
90+
message: hass.localize("ui.panel.lovelace.cards.actions.no_url"),
91+
});
92+
forwardHaptic("failure");
93+
}
94+
break;
95+
}
96+
case "toggle": {
97+
toggleEntity(hass, config.entity_id);
98+
forwardHaptic("light");
99+
break;
100+
}
101+
case "call-service": {
102+
if (!actionConfig.service) {
103+
showToast(node, {
104+
message: hass.localize("ui.panel.lovelace.cards.actions.no_service"),
105+
});
106+
forwardHaptic("failure");
107+
return;
108+
}
109+
const [domain, service] = actionConfig.service.split(".", 2);
110+
hass.callService(
111+
domain,
112+
service,
113+
// @ts-ignore
114+
actionConfig.data ?? actionConfig.service_data,
115+
actionConfig.target,
116+
);
117+
forwardHaptic("light");
118+
break;
119+
}
120+
case "fire-dom-event": {
121+
fireEvent(node, "ll-custom", actionConfig);
122+
}
123+
}
124+
};
125+
126+
declare global {
127+
interface HASSDomEvents {
128+
"hass-notification": ShowToastParams;
129+
}
130+
}

0 commit comments

Comments
 (0)