From b6d0d777bf766f64cd456218fe42d049417fb6b3 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Sun, 28 Oct 2018 15:47:21 -0400 Subject: [PATCH] Gauge convert and fix issues (#1886) * Gauge convert and fix issues * Fixing Unit_of_Measurement * Addressing Reviews * Updating typing --- src/panels/lovelace/cards/hui-gauge-card.js | 211 -------------- src/panels/lovelace/cards/hui-gauge-card.ts | 266 ++++++++++++++++++ .../lovelace/common/create-card-element.js | 2 +- 3 files changed, 267 insertions(+), 212 deletions(-) delete mode 100644 src/panels/lovelace/cards/hui-gauge-card.js create mode 100644 src/panels/lovelace/cards/hui-gauge-card.ts diff --git a/src/panels/lovelace/cards/hui-gauge-card.js b/src/panels/lovelace/cards/hui-gauge-card.js deleted file mode 100644 index ee8be76cff..0000000000 --- a/src/panels/lovelace/cards/hui-gauge-card.js +++ /dev/null @@ -1,211 +0,0 @@ -import { html } from "@polymer/polymer/lib/utils/html-tag.js"; -import { PolymerElement } from "@polymer/polymer/polymer-element.js"; - -import "../../../components/ha-card.js"; - -import EventsMixin from "../../../mixins/events-mixin.js"; - -/* - * @appliesMixin EventsMixin - */ -class HuiGaugeCard extends EventsMixin(PolymerElement) { - static get template() { - return html` - - -
-
-
-
-
-
[[_computeStateDisplay(_stateObj)]]
-
[[_computeTitle(_stateObj)]]
-
-
-
- `; - } - - static get properties() { - return { - hass: { - type: Object, - }, - _config: Object, - _stateObj: { - type: Object, - computed: "_computeStateObj(hass.states, _config.entity)", - observer: "_stateObjChanged", - }, - }; - } - - getCardSize() { - return 1; - } - - setConfig(config) { - if (!config || !config.entity) - throw new Error("Invalid card configuration"); - this._config = { min: 0, max: 100, ...config }; - } - - _computeStateObj(states, entityId) { - return states && entityId in states ? states[entityId] : null; - } - - _stateObjChanged(stateObj) { - if (!stateObj || isNaN(stateObj.state)) return; - - const config = this._config; - const turn = this._translateTurn(stateObj.state, config) / 10; - - this.$.gauge.style.transform = `rotate(${turn}turn)`; - this.$.gauge.style.backgroundColor = this._computeSeverity( - stateObj.state, - config.severity - ); - } - - _computeStateDisplay(stateObj) { - if (!stateObj || isNaN(stateObj.state)) return ""; - const unitOfMeasurement = - this._config.unit_of_measurement || - stateObj.attributes.unit_of_measurement || - ""; - return `${stateObj.state} ${unitOfMeasurement}`; - } - - _computeTitle(stateObj) { - if (!stateObj) { - this.$.title.className = "not-found"; - return "Entity not available: " + this._config.entity; - } - if (isNaN(stateObj.state)) { - this.$.title.className = "not-found"; - return "Entity is non-numeric: " + this._config.entity; - } - this.$.title.className = ""; - return this._config.title; - } - - _computeSeverity(stateValue, sections) { - const numberValue = Number(stateValue); - const severityMap = { - red: "var(--label-badge-red)", - green: "var(--label-badge-green)", - yellow: "var(--label-badge-yellow)", - normal: "var(--label-badge-blue)", - }; - - if (!sections) return severityMap.normal; - - const sectionsArray = Object.keys(sections); - const sortable = sectionsArray.map((severity) => [ - severity, - sections[severity], - ]); - - for (var i = 0; i < sortable.length; i++) { - if (severityMap[sortable[i][0]] == null || isNaN(sortable[i][1])) { - return severityMap.normal; - } - } - sortable.sort((a, b) => a[1] - b[1]); - - if (numberValue >= sortable[0][1] && numberValue < sortable[1][1]) { - return severityMap[sortable[0][0]]; - } - if (numberValue >= sortable[1][1] && numberValue < sortable[2][1]) { - return severityMap[sortable[1][0]]; - } - if (numberValue >= sortable[2][1]) { - return severityMap[sortable[2][0]]; - } - return severityMap.normal; - } - - _translateTurn(value, config) { - return (5 * (value - config.min)) / (config.max - config.min); - } - - _handleClick() { - this.fire("hass-more-info", { entityId: this._config.entity }); - } -} - -customElements.define("hui-gauge-card", HuiGaugeCard); diff --git a/src/panels/lovelace/cards/hui-gauge-card.ts b/src/panels/lovelace/cards/hui-gauge-card.ts new file mode 100644 index 0000000000..6fcd7b4f85 --- /dev/null +++ b/src/panels/lovelace/cards/hui-gauge-card.ts @@ -0,0 +1,266 @@ +import { + html, + LitElement, + PropertyDeclarations, + PropertyValues, +} from "@polymer/lit-element"; +import { LovelaceCard, LovelaceConfig } from "../types.js"; +import { HomeAssistant } from "../../../types.js"; +import isValidEntityId from "../../../common/entity/valid_entity_id.js"; +import { fireEvent } from "../../../common/dom/fire_event.js"; + +import "../../../components/ha-card.js"; + +interface Config extends LovelaceConfig { + entity: string; + title?: string; + unit_of_measurement?: string; + min?: number; + max?: number; + severity?: object; +} + +const severityMap = { + red: "var(--label-badge-red)", + green: "var(--label-badge-green)", + yellow: "var(--label-badge-yellow)", + normal: "var(--label-badge-blue)", +}; + +class HuiGaugeCard extends LitElement implements LovelaceCard { + public hass?: HomeAssistant; + private _config?: Config; + + static get properties(): PropertyDeclarations { + return { + hass: {}, + _config: {}, + }; + } + + public getCardSize() { + return 2; + } + + public setConfig(config) { + if (!config || !config.entity) { + throw new Error("Invalid card configuration"); + } + if (!isValidEntityId(config.entity)) { + throw new Error("Invalid Entity"); + } + this._config = { min: 0, max: 100, ...config }; + } + + protected render() { + if (!this._config || !this.hass) { + return html``; + } + const stateObj = this.hass.states[this._config.entity]; + let error; + if (!stateObj) { + error = "Entity not available: " + this._config.entity; + } else if (isNaN(Number(stateObj.state))) { + error = "Entity is non-numeric: " + this._config.entity; + } + + return html` + ${this.renderStyle()} + + ${ + error + ? html`
${error}
` + : html` +
+
+
+
+
+
${stateObj.state} + ${this._config.unit_of_measurement || + stateObj.attributes.unit_of_measurement || + ""} +
+
${this._config.title} + +
+
+
+ ` + } +
+ `; + } + + protected shouldUpdate(changedProps: PropertyValues) { + if (changedProps.get("hass")) { + return ( + (changedProps.get("hass") as any).states[this._config!.entity] !== + this.hass!.states[this._config!.entity] + ); + } + if (changedProps.get("_config")) { + return changedProps.get("_config") !== this._config; + } + return (changedProps as unknown) as boolean; + } + + protected updated() { + if ( + !this._config || + !this.hass || + !this.shadowRoot!.getElementById("gauge") + ) { + return; + } + const stateObj = this.hass.states[this._config.entity]; + if (isNaN(Number(stateObj.state))) { + return; + } + + const turn = this._translateTurn(Number(stateObj.state), this._config); + + this.shadowRoot!.getElementById( + "gauge" + )!.style.cssText = `transform: rotate(${turn}turn); background-color: ${this._computeSeverity( + stateObj.state, + this._config.severity! + )}`; + + (this.shadowRoot!.querySelector( + "ha-card" + )! as HTMLElement).style.setProperty( + "--base-unit", + this._computeBaseUnit() + ); + } + + private renderStyle() { + return html` + + `; + } + + private _computeSeverity(stateValue: string, sections: object) { + const numberValue = Number(stateValue); + + if (!sections) { + return severityMap.normal; + } + + const sectionsArray = Object.keys(sections); + const sortable = sectionsArray.map((severity) => [ + severity, + sections[severity], + ]); + + for (const severity of sortable) { + if (severityMap[severity[0]] == null || isNaN(severity[1])) { + return severityMap.normal; + } + } + sortable.sort((a, b) => a[1] - b[1]); + + if (numberValue >= sortable[0][1] && numberValue < sortable[1][1]) { + return severityMap[sortable[0][0]]; + } + if (numberValue >= sortable[1][1] && numberValue < sortable[2][1]) { + return severityMap[sortable[1][0]]; + } + if (numberValue >= sortable[2][1]) { + return severityMap[sortable[2][0]]; + } + return severityMap.normal; + } + + private _translateTurn(value: number, config: Config) { + const maxTurnValue = Math.min(Math.max(value, config.min!), config.max!); + return ( + (5 * (maxTurnValue - config.min!)) / (config.max! - config.min!) / 10 + ); + } + + private _computeBaseUnit() { + return this.clientWidth < 200 ? this.clientWidth / 5 + "px" : "50px"; + } + + private _handleClick() { + fireEvent(this, "hass-more-info", { entityId: this._config!.entity }); + } +} + +customElements.define("hui-gauge-card", HuiGaugeCard); diff --git a/src/panels/lovelace/common/create-card-element.js b/src/panels/lovelace/common/create-card-element.js index 3cadc4b052..3759bc814c 100644 --- a/src/panels/lovelace/common/create-card-element.js +++ b/src/panels/lovelace/common/create-card-element.js @@ -22,7 +22,7 @@ import "../cards/hui-sensor-card.js"; import "../cards/hui-vertical-stack-card.ts"; import "../cards/hui-thermostat-card.ts"; import "../cards/hui-weather-forecast-card"; -import "../cards/hui-gauge-card.js"; +import "../cards/hui-gauge-card"; import createErrorCardConfig from "./create-error-card-config.js";