support actions on rows (#4023)

* support actions on rows

* address comments

* add type

* pointer events

* move action area to row name to avoid handler competition

* add action to state-badge as well

* correct type

* address comments

* handle 'enter' in long-press and make entities state-badge selecatable
This commit is contained in:
Ian Richardson 2019-10-23 12:30:09 -05:00 committed by Paulus Schoutsen
parent e435b9153b
commit 39d052273d
5 changed files with 112 additions and 26 deletions

View File

@ -12,16 +12,12 @@ import {
import "../../../components/ha-card";
import "../components/hui-entities-toggle";
import { fireEvent } from "../../../common/dom/fire_event";
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
import { HomeAssistant } from "../../../types";
import { EntityRow } from "../entity-rows/types";
import { LovelaceCard, LovelaceCardEditor } from "../types";
import { processConfigEntities } from "../common/process-config-entities";
import { createRowElement } from "../common/create-row-element";
import { EntitiesCardConfig, EntitiesCardEntityConfig } from "./types";
import { computeDomain } from "../../../common/entity/compute_domain";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
@customElement("hui-entities-card")
@ -161,10 +157,6 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
overflow: hidden;
}
.state-card-dialog {
cursor: pointer;
}
.icon {
padding: 0px 18px 0px 8px;
}
@ -176,23 +168,11 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
if (this._hass) {
element.hass = this._hass;
}
if (
entityConf.entity &&
!DOMAINS_HIDE_MORE_INFO.includes(computeDomain(entityConf.entity))
) {
element.classList.add("state-card-dialog");
element.addEventListener("click", () => this._handleClick(entityConf));
}
return html`
<div>${element}</div>
`;
}
private _handleClick(entityConf: EntitiesCardEntityConfig): void {
const entityId = entityConf.entity;
fireEvent(this, "hass-more-info", { entityId });
}
}
declare global {

View File

@ -28,6 +28,9 @@ export interface EntitiesCardEntityConfig extends EntityConfig {
service?: string;
service_data?: object;
url?: string;
tap_action?: ActionConfig;
hold_action?: ActionConfig;
double_tap_action?: ActionConfig;
}
export interface EntitiesCardConfig extends LovelaceCardConfig {

View File

@ -138,9 +138,16 @@ class LongPress extends HTMLElement implements LongPress {
window.setTimeout(() => (this.cooldownEnd = false), 100);
};
const handleEnter = (ev: Event) => {
if ((ev as KeyboardEvent).keyCode === 13) {
return clickEnd(ev);
}
};
element.addEventListener("touchstart", clickStart, { passive: true });
element.addEventListener("touchend", clickEnd);
element.addEventListener("touchcancel", clickEnd);
element.addEventListener("keyup", handleEnter);
// iOS 13 sends a complete normal touchstart-touchend series of events followed by a mousedown-click series.
// That might be a bug, but until it's fixed, this should make long-press work.

View File

@ -16,8 +16,14 @@ import "../components/hui-warning";
import { HomeAssistant } from "../../../types";
import { computeRTL } from "../../../common/util/compute_rtl";
import { EntitiesCardEntityConfig } from "../cards/types";
import { toggleAttribute } from "../../../common/dom/toggle_attribute";
import { longPress } from "../common/directives/long-press-directive";
import { hasDoubleClick } from "../common/has-double-click";
import { handleClick } from "../common/handle-click";
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
import { computeDomain } from "../../../common/entity/compute_domain";
import { classMap } from "lit-html/directives/class-map";
import { EntitiesCardEntityConfig } from "../cards/types";
class HuiGenericEntityRow extends LitElement {
@property() public hass?: HomeAssistant;
@ -46,15 +52,45 @@ class HuiGenericEntityRow extends LitElement {
`;
}
const pointer =
(this.config.tap_action && this.config.tap_action.action !== "none") ||
(this.config.entity &&
!DOMAINS_HIDE_MORE_INFO.includes(computeDomain(this.config.entity)));
return html`
<state-badge
class=${classMap({
pointer,
})}
.hass=${this.hass}
.stateObj=${stateObj}
.overrideIcon=${this.config.icon}
.overrideImage=${this.config.image}
@ha-click=${this._handleClick}
@ha-hold=${this._handleHold}
@ha-dblclick=${this._handleDblClick}
.longPress=${longPress({
hasDoubleClick: hasDoubleClick(this.config.double_tap_action),
})}
tabindex="0"
></state-badge>
<div class="flex">
<div class="info">
<div
class=${classMap({
info: true,
pointer,
padName: this.showSecondary && !this.config.secondary_info,
padSecondary: Boolean(
!this.showSecondary || this.config.secondary_info
),
})}
@ha-click=${this._handleClick}
@ha-hold=${this._handleHold}
@ha-dblclick=${this._handleDblClick}
.longPress=${longPress({
hasDoubleClick: hasDoubleClick(this.config.double_tap_action),
})}
>
${this.config.name || computeStateName(stateObj)}
<div class="secondary">
${!this.showSecondary
@ -86,6 +122,18 @@ class HuiGenericEntityRow extends LitElement {
}
}
private _handleClick(): void {
handleClick(this, this.hass!, this.config!, false, false);
}
private _handleHold(): void {
handleClick(this, this.hass!, this.config!, true, false);
}
private _handleDblClick(): void {
handleClick(this, this.hass!, this.config!, false, true);
}
static get styles(): CSSResult {
return css`
:host {
@ -132,6 +180,15 @@ class HuiGenericEntityRow extends LitElement {
margin-left: 0;
margin-right: 8px;
}
.pointer {
cursor: pointer;
}
.padName {
padding: 12px 0px;
}
.padSecondary {
padding: 4px 0px;
}
`;
}
}

View File

@ -18,19 +18,26 @@ import "../components/hui-warning";
import { computeStateName } from "../../../common/entity/compute_state_name";
import { HomeAssistant, InputSelectEntity } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { EntityRow } from "./types";
import { setInputSelectOption } from "../../../data/input-select";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import { forwardHaptic } from "../../../data/haptics";
import { stopPropagation } from "../../../common/dom/stop_propagation";
import { longPress } from "../common/directives/long-press-directive";
import { hasDoubleClick } from "../common/has-double-click";
import { handleClick } from "../common/handle-click";
import { classMap } from "lit-html/directives/class-map";
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
import { computeDomain } from "../../../common/entity/compute_domain";
import { EntitiesCardEntityConfig } from "../cards/types";
@customElement("hui-input-select-entity-row")
class HuiInputSelectEntityRow extends LitElement implements EntityRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;
@property() private _config?: EntitiesCardEntityConfig;
public setConfig(config: EntityConfig): void {
public setConfig(config: EntitiesCardEntityConfig): void {
if (!config || !config.entity) {
throw new Error("Invalid Configuration: 'entity' required");
}
@ -63,8 +70,25 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow {
`;
}
const pointer =
(this._config.tap_action && this._config.tap_action.action !== "none") ||
(this._config.entity &&
!DOMAINS_HIDE_MORE_INFO.includes(computeDomain(this._config.entity)));
return html`
<state-badge .stateObj="${stateObj}"></state-badge>
<state-badge
.stateObj=${stateObj}
class=${classMap({
pointer,
})}
@ha-click=${this._handleClick}
@ha-hold=${this._handleHold}
@ha-dblclick=${this._handleDblClick}
.longPress=${longPress({
hasDoubleClick: hasDoubleClick(this._config.double_tap_action),
})}
tabindex="0"
></state-badge>
<ha-paper-dropdown-menu
.label=${this._config.name || computeStateName(stateObj)}
.value=${stateObj.state}
@ -103,6 +127,18 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow {
)!.selected = stateObj.attributes.options.indexOf(stateObj.state);
}
private _handleClick(): void {
handleClick(this, this.hass!, this._config!, false, false);
}
private _handleHold(): void {
handleClick(this, this.hass!, this._config!, true, false);
}
private _handleDblClick(): void {
handleClick(this, this.hass!, this._config!, false, true);
}
static get styles(): CSSResult {
return css`
:host {
@ -118,6 +154,9 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow {
cursor: pointer;
min-width: 200px;
}
.pointer {
cursor: pointer;
}
`;
}