mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Add configurable actions to Gauge Card (#20833)
* Add actions to gauge card * struct support * tap_action in UI * Apply suggestions from code review Co-authored-by: Paul Bottein <paul.bottein@gmail.com> * typo --------- Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
This commit is contained in:
parent
2113cf5280
commit
9fe8f507ec
@ -8,17 +8,22 @@ import {
|
|||||||
nothing,
|
nothing,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
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 { styleMap } from "lit/directives/style-map";
|
||||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
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 { computeStateName } from "../../../common/entity/compute_state_name";
|
||||||
import { isValidEntityId } from "../../../common/entity/valid_entity_id";
|
import { isValidEntityId } from "../../../common/entity/valid_entity_id";
|
||||||
import { getNumberFormatOptions } from "../../../common/number/format_number";
|
import { getNumberFormatOptions } from "../../../common/number/format_number";
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../../../components/ha-gauge";
|
import "../../../components/ha-gauge";
|
||||||
import { UNAVAILABLE } from "../../../data/entity";
|
import { UNAVAILABLE } from "../../../data/entity";
|
||||||
|
import { ActionHandlerEvent } from "../../../data/lovelace/action_handler";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||||
import { findEntities } from "../common/find-entities";
|
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 { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||||
import { createEntityNotFoundWarning } from "../components/hui-warning";
|
import { createEntityNotFoundWarning } from "../components/hui-warning";
|
||||||
import type { LovelaceCard, LovelaceCardEditor } from "../types";
|
import type { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
@ -123,10 +128,26 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
const name = this._config.name ?? computeStateName(stateObj);
|
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)
|
// Use `stateObj.state` as value to keep formatting (e.g trailing zeros)
|
||||||
// for consistent value display across gauge, entity, entity-row, etc.
|
// for consistent value display across gauge, entity, entity-row, etc.
|
||||||
return html`
|
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
|
<ha-gauge
|
||||||
.min=${this._config.min!}
|
.min=${this._config.min!}
|
||||||
.max=${this._config.max!}
|
.max=${this._config.max!}
|
||||||
@ -256,14 +277,13 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleClick(): void {
|
private _handleAction(ev: ActionHandlerEvent) {
|
||||||
fireEvent(this, "hass-more-info", { entityId: this._config!.entity });
|
handleAction(this, this.hass!, this._config!, ev.detail.action!);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return css`
|
return css`
|
||||||
ha-card {
|
ha-card {
|
||||||
cursor: pointer;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
@ -274,6 +294,10 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ha-card.action {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
ha-card:focus {
|
ha-card:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
@ -235,6 +235,9 @@ export interface GaugeCardConfig extends LovelaceCardConfig {
|
|||||||
theme?: string;
|
theme?: string;
|
||||||
needle?: boolean;
|
needle?: boolean;
|
||||||
segments?: GaugeSegment[];
|
segments?: GaugeSegment[];
|
||||||
|
tap_action?: ActionConfig;
|
||||||
|
hold_action?: ActionConfig;
|
||||||
|
double_tap_action?: ActionConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConfigEntity extends EntityConfig {
|
export interface ConfigEntity extends EntityConfig {
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
number,
|
number,
|
||||||
object,
|
object,
|
||||||
optional,
|
optional,
|
||||||
|
refine,
|
||||||
string,
|
string,
|
||||||
} from "superstruct";
|
} from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
@ -17,8 +18,12 @@ import type { SchemaUnion } from "../../../../components/ha-form/types";
|
|||||||
import type { HomeAssistant } from "../../../../types";
|
import type { HomeAssistant } from "../../../../types";
|
||||||
import type { GaugeCardConfig } from "../../cards/types";
|
import type { GaugeCardConfig } from "../../cards/types";
|
||||||
import type { LovelaceCardEditor } from "../../types";
|
import type { LovelaceCardEditor } from "../../types";
|
||||||
|
import { actionConfigStruct } from "../structs/action-struct";
|
||||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||||
import { DEFAULT_MIN, DEFAULT_MAX } from "../../cards/hui-gauge-card";
|
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({
|
const gaugeSegmentStruct = object({
|
||||||
from: number(),
|
from: number(),
|
||||||
@ -38,6 +43,13 @@ const cardConfigStruct = assign(
|
|||||||
theme: optional(string()),
|
theme: optional(string()),
|
||||||
needle: optional(boolean()),
|
needle: optional(boolean()),
|
||||||
segments: optional(array(gaugeSegmentStruct)),
|
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),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -121,6 +133,15 @@ export class HuiGaugeCardEditor
|
|||||||
},
|
},
|
||||||
] as const)
|
] as const)
|
||||||
: []),
|
: []),
|
||||||
|
{
|
||||||
|
name: "tap_action",
|
||||||
|
selector: {
|
||||||
|
ui_action: {
|
||||||
|
actions: TAP_ACTIONS,
|
||||||
|
default_action: "more-info",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
] as const
|
] as const
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -210,6 +231,12 @@ export class HuiGaugeCardEditor
|
|||||||
return this.hass!.localize(
|
return this.hass!.localize(
|
||||||
"ui.panel.lovelace.editor.card.generic.unit"
|
"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:
|
default:
|
||||||
// "green" | "yellow" | "red"
|
// "green" | "yellow" | "red"
|
||||||
return this.hass!.localize(
|
return this.hass!.localize(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user