Skip to content

Commit

Permalink
Add configurable actions to Gauge Card (#20833)
Browse files Browse the repository at this point in the history
* Add actions to gauge card

* struct support

* tap_action in UI

* Apply suggestions from code review

Co-authored-by: Paul Bottein <[email protected]>

* typo

---------

Co-authored-by: Paul Bottein <[email protected]>
  • Loading branch information
karwosts and piitaya authored May 22, 2024
1 parent 2113cf5 commit 9fe8f50
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 5 deletions.
34 changes: 29 additions & 5 deletions src/panels/lovelace/cards/hui-gauge-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,22 @@ import {
nothing,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { classMap } from "lit/directives/class-map";
import { styleMap } from "lit/directives/style-map";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { fireEvent } from "../../../common/dom/fire_event";
import { computeStateName } from "../../../common/entity/compute_state_name";
import { isValidEntityId } from "../../../common/entity/valid_entity_id";
import { getNumberFormatOptions } from "../../../common/number/format_number";
import "../../../components/ha-card";
import "../../../components/ha-gauge";
import { UNAVAILABLE } from "../../../data/entity";
import { ActionHandlerEvent } from "../../../data/lovelace/action_handler";
import type { HomeAssistant } from "../../../types";
import { actionHandler } from "../common/directives/action-handler-directive";
import { findEntities } from "../common/find-entities";
import { handleAction } from "../common/handle-action";
import { hasAction } from "../common/has-action";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import type { LovelaceCard, LovelaceCardEditor } from "../types";
Expand Down Expand Up @@ -123,10 +128,26 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {

const name = this._config.name ?? computeStateName(stateObj);

const hasAnyAction =
!this._config.tap_action ||
hasAction(this._config.tap_action) ||
hasAction(this._config.hold_action) ||
hasAction(this._config.double_tap_action);

// Use `stateObj.state` as value to keep formatting (e.g trailing zeros)
// for consistent value display across gauge, entity, entity-row, etc.
return html`
<ha-card @click=${this._handleClick} tabindex="0">
<ha-card
class=${classMap({ action: hasAnyAction })}
@action=${this._handleAction}
.actionHandler=${actionHandler({
hasHold: hasAction(this._config.hold_action),
hasDoubleClick: hasAction(this._config.double_tap_action),
})}
tabindex=${ifDefined(
hasAction(this._config.tap_action) ? "0" : undefined
)}
>
<ha-gauge
.min=${this._config.min!}
.max=${this._config.max!}
Expand Down Expand Up @@ -256,14 +277,13 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
}));
}

private _handleClick(): void {
fireEvent(this, "hass-more-info", { entityId: this._config!.entity });
private _handleAction(ev: ActionHandlerEvent) {
handleAction(this, this.hass!, this._config!, ev.detail.action!);
}

static get styles(): CSSResultGroup {
return css`
ha-card {
cursor: pointer;
height: 100%;
overflow: hidden;
padding: 16px;
Expand All @@ -274,6 +294,10 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
box-sizing: border-box;
}
ha-card.action {
cursor: pointer;
}
ha-card:focus {
outline: none;
}
Expand Down
3 changes: 3 additions & 0 deletions src/panels/lovelace/cards/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ export interface GaugeCardConfig extends LovelaceCardConfig {
theme?: string;
needle?: boolean;
segments?: GaugeSegment[];
tap_action?: ActionConfig;
hold_action?: ActionConfig;
double_tap_action?: ActionConfig;
}

export interface ConfigEntity extends EntityConfig {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
number,
object,
optional,
refine,
string,
} from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event";
Expand All @@ -17,8 +18,12 @@ import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types";
import type { GaugeCardConfig } from "../../cards/types";
import type { LovelaceCardEditor } from "../../types";
import { actionConfigStruct } from "../structs/action-struct";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { DEFAULT_MIN, DEFAULT_MAX } from "../../cards/hui-gauge-card";
import { UiAction } from "../../components/hui-action-editor";

const TAP_ACTIONS: UiAction[] = ["navigate", "url", "call-service", "none"];

const gaugeSegmentStruct = object({
from: number(),
Expand All @@ -38,6 +43,13 @@ const cardConfigStruct = assign(
theme: optional(string()),
needle: optional(boolean()),
segments: optional(array(gaugeSegmentStruct)),
tap_action: optional(
refine(actionConfigStruct, TAP_ACTIONS.toString(), (value) =>
TAP_ACTIONS.includes(value.action)
)
),
hold_action: optional(actionConfigStruct),
double_tap_action: optional(actionConfigStruct),
})
);

Expand Down Expand Up @@ -121,6 +133,15 @@ export class HuiGaugeCardEditor
},
] as const)
: []),
{
name: "tap_action",
selector: {
ui_action: {
actions: TAP_ACTIONS,
default_action: "more-info",
},
},
},
] as const
);

Expand Down Expand Up @@ -210,6 +231,12 @@ export class HuiGaugeCardEditor
return this.hass!.localize(
"ui.panel.lovelace.editor.card.generic.unit"
);
case "tap_action":
return `${this.hass!.localize(
`ui.panel.lovelace.editor.card.generic.${schema.name}`
)} (${this.hass!.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})`;
default:
// "green" | "yellow" | "red"
return this.hass!.localize(
Expand Down

0 comments on commit 9fe8f50

Please sign in to comment.