From 03080973be7b1aa4e0717c1783bb9574dcc9046d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Fri, 30 Jul 2021 10:51:21 +0200 Subject: [PATCH] Add needle option to ha-gauge and gauge card (#9637) --- src/components/ha-gauge.ts | 77 ++++++++++++++++--- src/panels/lovelace/cards/hui-gauge-card.ts | 16 ++++ src/panels/lovelace/cards/types.ts | 1 + .../config-elements/hui-gauge-card-editor.ts | 30 +++++++- src/translations/en.json | 1 + 5 files changed, 112 insertions(+), 13 deletions(-) diff --git a/src/components/ha-gauge.ts b/src/components/ha-gauge.ts index e5d785b435..2322f2e28a 100644 --- a/src/components/ha-gauge.ts +++ b/src/components/ha-gauge.ts @@ -13,6 +13,11 @@ const getAngle = (value: number, min: number, max: number) => { return (percentage * 180) / 100; }; +interface LevelDefinition { + level: number; + stroke: string; +} + @customElement("ha-gauge") export class Gauge extends LitElement { @property({ type: Number }) public min = 0; @@ -23,6 +28,10 @@ export class Gauge extends LitElement { @property() public locale!: FrontendLocaleData; + @property({ type: Boolean }) public needle?: boolean; + + @property() public levels?: LevelDefinition[]; + @property() public label = ""; @state() private _angle = 0; @@ -55,18 +64,53 @@ export class Gauge extends LitElement { class="dial" d="M 10 50 A 40 40 0 0 1 90 50" > - + + ${ + this.levels + ? this.levels + .sort((a, b) => a.level - b.level) + .map((level) => { + const angle = getAngle(level.level, this.min, this.max); + return svg``; + }) + : "" + } + ${ + this.needle + ? svg` + ` + : svg`` + } ${ // Workaround for https://github.com/home-assistant/frontend/issues/6467 isSafari @@ -117,6 +161,15 @@ export class Gauge extends LitElement { transform-origin: 50% 100%; transition: all 1s ease 0s; } + .needle { + fill: var(--primary-text-color); + transform-origin: 50% 100%; + transition: all 1s ease 0s; + } + .level { + fill: none; + stroke-width: 15; + } .gauge { display: block; } diff --git a/src/panels/lovelace/cards/hui-gauge-card.ts b/src/panels/lovelace/cards/hui-gauge-card.ts index f87a9081e8..1db4cb6334 100644 --- a/src/panels/lovelace/cards/hui-gauge-card.ts +++ b/src/panels/lovelace/cards/hui-gauge-card.ts @@ -135,6 +135,8 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { style=${styleMap({ "--gauge-color": this._computeSeverity(entityState), })} + .needle=${this._config!.needle} + .levels=${this._config!.needle ? this._severityLevels() : undefined} >
${this._config.name || computeStateName(stateObj)} @@ -200,6 +202,20 @@ class HuiGaugeCard extends LitElement implements LovelaceCard { return severityMap.normal; } + private _severityLevels() { + const sections = this._config!.severity; + + if (!sections) { + return []; + } + + const sectionsArray = Object.keys(sections); + return sectionsArray.map((severity) => ({ + level: sections[severity], + stroke: severityMap[severity], + })); + } + private _handleClick(): void { fireEvent(this, "hass-more-info", { entityId: this._config!.entity }); } diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts index 88684adfa8..5d191334a3 100644 --- a/src/panels/lovelace/cards/types.ts +++ b/src/panels/lovelace/cards/types.ts @@ -164,6 +164,7 @@ export interface GaugeCardConfig extends LovelaceCardConfig { max?: number; severity?: SeverityConfig; theme?: string; + needle?: boolean; } export interface ConfigEntity extends EntityConfig { diff --git a/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts index 16e1e049c9..3776dee7b0 100644 --- a/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-gauge-card-editor.ts @@ -1,7 +1,7 @@ import "@polymer/paper-input/paper-input"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; -import { assert, number, object, optional, string } from "superstruct"; +import { assert, boolean, number, object, optional, string } from "superstruct"; import { fireEvent } from "../../../../common/dom/fire_event"; import { computeRTLDirection } from "../../../../common/util/compute_rtl"; import "../../../../components/ha-formfield"; @@ -23,6 +23,7 @@ const cardConfigStruct = object({ max: optional(number()), severity: optional(object()), theme: optional(string()), + needle: optional(boolean()), }); const includeDomains = ["counter", "input_number", "number", "sensor"]; @@ -137,6 +138,17 @@ export class HuiGaugeCardEditor .configValue=${"max"} @value-changed="${this._valueChanged}" > + +