mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-01 13:37:47 +00:00
Convert more-info-weather to LitElement (#4073)
* Convert more-info-weather to LitElement * address comments * add shouldUpdate
This commit is contained in:
parent
0078b48e3c
commit
be678b02c5
@ -1,235 +0,0 @@
|
||||
import "@polymer/iron-icon/iron-icon";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
|
||||
import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
|
||||
/*
|
||||
* @appliesMixin LocalizeMixin
|
||||
*/
|
||||
class MoreInfoWeather extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
iron-icon {
|
||||
color: var(--paper-item-icon-color);
|
||||
}
|
||||
.section {
|
||||
margin: 16px 0 8px 0;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
height: 32px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
.temp,
|
||||
.templow {
|
||||
min-width: 48px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.templow {
|
||||
margin: 0 16px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
.attribution {
|
||||
color: var(--secondary-text-color);
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:thermometer"></iron-icon>
|
||||
<div class="main">
|
||||
[[localize('ui.card.weather.attributes.temperature')]]
|
||||
</div>
|
||||
<div>
|
||||
[[stateObj.attributes.temperature]] [[getUnit('temperature')]]
|
||||
</div>
|
||||
</div>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.pressure)]]">
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:gauge"></iron-icon>
|
||||
<div class="main">
|
||||
[[localize('ui.card.weather.attributes.air_pressure')]]
|
||||
</div>
|
||||
<div>
|
||||
[[stateObj.attributes.pressure]] [[getUnit('air_pressure')]]
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.humidity)]]">
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:water-percent"></iron-icon>
|
||||
<div class="main">
|
||||
[[localize('ui.card.weather.attributes.humidity')]]
|
||||
</div>
|
||||
<div>[[stateObj.attributes.humidity]] %</div>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.wind_speed)]]">
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:weather-windy"></iron-icon>
|
||||
<div class="main">
|
||||
[[localize('ui.card.weather.attributes.wind_speed')]]
|
||||
</div>
|
||||
<div>
|
||||
[[getWind(stateObj.attributes.wind_speed,
|
||||
stateObj.attributes.wind_bearing, localize)]]
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.visibility)]]">
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:eye"></iron-icon>
|
||||
<div class="main">
|
||||
[[localize('ui.card.weather.attributes.visibility')]]
|
||||
</div>
|
||||
<div>[[stateObj.attributes.visibility]] [[getUnit('length')]]</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[stateObj.attributes.forecast]]">
|
||||
<div class="section">[[localize('ui.card.weather.forecast')]]:</div>
|
||||
<template is="dom-repeat" items="[[stateObj.attributes.forecast]]">
|
||||
<div class="flex">
|
||||
<template is="dom-if" if="[[_showValue(item.condition)]]">
|
||||
<iron-icon icon="[[getWeatherIcon(item.condition)]]"></iron-icon>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_showValue(item.templow)]]">
|
||||
<div class="main">[[computeDateTime(item.datetime)]]</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(item.templow)]]">
|
||||
<div class="main">[[computeDate(item.datetime)]]</div>
|
||||
<div class="templow">
|
||||
[[item.templow]] [[getUnit('temperature')]]
|
||||
</div>
|
||||
</template>
|
||||
<div class="temp">
|
||||
[[item.temperature]] [[getUnit('temperature')]]
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="stateObj.attributes.attribution">
|
||||
<div class="attribution">[[stateObj.attributes.attribution]]</div>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
stateObj: Object,
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.cardinalDirections = [
|
||||
"N",
|
||||
"NNE",
|
||||
"NE",
|
||||
"ENE",
|
||||
"E",
|
||||
"ESE",
|
||||
"SE",
|
||||
"SSE",
|
||||
"S",
|
||||
"SSW",
|
||||
"SW",
|
||||
"WSW",
|
||||
"W",
|
||||
"WNW",
|
||||
"NW",
|
||||
"NNW",
|
||||
"N",
|
||||
];
|
||||
this.weatherIcons = {
|
||||
"clear-night": "hass:weather-night",
|
||||
cloudy: "hass:weather-cloudy",
|
||||
exceptional: "hass:alert-circle-outline",
|
||||
fog: "hass:weather-fog",
|
||||
hail: "hass:weather-hail",
|
||||
lightning: "hass:weather-lightning",
|
||||
"lightning-rainy": "hass:weather-lightning-rainy",
|
||||
partlycloudy: "hass:weather-partly-cloudy",
|
||||
pouring: "hass:weather-pouring",
|
||||
rainy: "hass:weather-rainy",
|
||||
snowy: "hass:weather-snowy",
|
||||
"snowy-rainy": "hass:weather-snowy-rainy",
|
||||
sunny: "hass:weather-sunny",
|
||||
windy: "hass:weather-windy",
|
||||
"windy-variant": "hass:weather-windy-variant",
|
||||
};
|
||||
}
|
||||
|
||||
computeDate(data) {
|
||||
const date = new Date(data);
|
||||
return date.toLocaleDateString(this.hass.language, {
|
||||
weekday: "long",
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
});
|
||||
}
|
||||
|
||||
computeDateTime(data) {
|
||||
const date = new Date(data);
|
||||
return date.toLocaleDateString(this.hass.language, {
|
||||
weekday: "long",
|
||||
hour: "numeric",
|
||||
});
|
||||
}
|
||||
|
||||
getUnit(measure) {
|
||||
const lengthUnit = this.hass.config.unit_system.length || "";
|
||||
switch (measure) {
|
||||
case "air_pressure":
|
||||
return lengthUnit === "km" ? "hPa" : "inHg";
|
||||
case "length":
|
||||
return lengthUnit;
|
||||
case "precipitation":
|
||||
return lengthUnit === "km" ? "mm" : "in";
|
||||
default:
|
||||
return this.hass.config.unit_system[measure] || "";
|
||||
}
|
||||
}
|
||||
|
||||
windBearingToText(degree) {
|
||||
const degreenum = parseInt(degree);
|
||||
if (isFinite(degreenum)) {
|
||||
return this.cardinalDirections[(((degreenum + 11.25) / 22.5) | 0) % 16];
|
||||
}
|
||||
return degree;
|
||||
}
|
||||
|
||||
getWind(speed, bearing, localize) {
|
||||
if (bearing != null) {
|
||||
const cardinalDirection = this.windBearingToText(bearing);
|
||||
return `${speed} ${this.getUnit("length")}/h (${localize(
|
||||
`ui.card.weather.cardinal_direction.${cardinalDirection.toLowerCase()}`
|
||||
) || cardinalDirection})`;
|
||||
}
|
||||
return `${speed} ${this.getUnit("length")}/h`;
|
||||
}
|
||||
|
||||
getWeatherIcon(condition) {
|
||||
return this.weatherIcons[condition];
|
||||
}
|
||||
|
||||
_showValue(item) {
|
||||
return typeof item !== "undefined" && item !== null;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("more-info-weather", MoreInfoWeather);
|
288
src/dialogs/more-info/controls/more-info-weather.ts
Normal file
288
src/dialogs/more-info/controls/more-info-weather.ts
Normal file
@ -0,0 +1,288 @@
|
||||
import "@polymer/iron-icon/iron-icon";
|
||||
import {
|
||||
LitElement,
|
||||
property,
|
||||
CSSResult,
|
||||
css,
|
||||
customElement,
|
||||
PropertyValues,
|
||||
} from "lit-element";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { TemplateResult, html } from "lit-html";
|
||||
|
||||
import { HomeAssistant } from "../../../types";
|
||||
|
||||
const cardinalDirections = [
|
||||
"N",
|
||||
"NNE",
|
||||
"NE",
|
||||
"ENE",
|
||||
"E",
|
||||
"ESE",
|
||||
"SE",
|
||||
"SSE",
|
||||
"S",
|
||||
"SSW",
|
||||
"SW",
|
||||
"WSW",
|
||||
"W",
|
||||
"WNW",
|
||||
"NW",
|
||||
"NNW",
|
||||
"N",
|
||||
];
|
||||
|
||||
const weatherIcons = {
|
||||
"clear-night": "hass:weather-night",
|
||||
cloudy: "hass:weather-cloudy",
|
||||
exceptional: "hass:alert-circle-outline",
|
||||
fog: "hass:weather-fog",
|
||||
hail: "hass:weather-hail",
|
||||
lightning: "hass:weather-lightning",
|
||||
"lightning-rainy": "hass:weather-lightning-rainy",
|
||||
partlycloudy: "hass:weather-partly-cloudy",
|
||||
pouring: "hass:weather-pouring",
|
||||
rainy: "hass:weather-rainy",
|
||||
snowy: "hass:weather-snowy",
|
||||
"snowy-rainy": "hass:weather-snowy-rainy",
|
||||
sunny: "hass:weather-sunny",
|
||||
windy: "hass:weather-windy",
|
||||
"windy-variant": "hass:weather-windy-variant",
|
||||
};
|
||||
|
||||
@customElement("more-info-weather")
|
||||
class MoreInfoWeather extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() public stateObj?: HassEntity;
|
||||
|
||||
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||
if (changedProps.has("stateObj")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (
|
||||
!oldHass ||
|
||||
oldHass.language !== this.hass.language ||
|
||||
oldHass.config.unit_system !== this.hass.config.unit_system
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (!this.hass || !this.stateObj) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
return html`
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:thermometer"></iron-icon>
|
||||
<div class="main">
|
||||
${this.hass.localize("ui.card.weather.attributes.temperature")}
|
||||
</div>
|
||||
<div>
|
||||
${this.stateObj.attributes.temperature} ${this.getUnit("temperature")}
|
||||
</div>
|
||||
</div>
|
||||
${this.stateObj.attributes.pressure
|
||||
? html`
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:gauge"></iron-icon>
|
||||
<div class="main">
|
||||
${this.hass.localize("ui.card.weather.attributes.air_pressure")}
|
||||
</div>
|
||||
<div>
|
||||
${this.stateObj.attributes.pressure}
|
||||
${this.getUnit("air_pressure")}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
${this.stateObj.attributes.humidity
|
||||
? html`
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:water-percent"></iron-icon>
|
||||
<div class="main">
|
||||
${this.hass.localize("ui.card.weather.attributes.humidity")}
|
||||
</div>
|
||||
<div>${this.stateObj.attributes.humidity} %</div>
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
${this.stateObj.attributes.wind_speed
|
||||
? html`
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:weather-windy"></iron-icon>
|
||||
<div class="main">
|
||||
${this.hass.localize("ui.card.weather.attributes.wind_speed")}
|
||||
</div>
|
||||
<div>
|
||||
${this.getWind(
|
||||
this.stateObj.attributes.wind_speed,
|
||||
this.stateObj.attributes.wind_bearing
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
${this.stateObj.attributes.visibility
|
||||
? html`
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:eye"></iron-icon>
|
||||
<div class="main">
|
||||
${this.hass.localize("ui.card.weather.attributes.visibility")}
|
||||
</div>
|
||||
<div>
|
||||
${this.stateObj.attributes.visibility} ${this.getUnit("length")}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
${this.stateObj.attributes.forecast
|
||||
? html`
|
||||
<div class="section">
|
||||
${this.hass.localize("ui.card.weather.forecast")}:
|
||||
</div>
|
||||
${this.stateObj.attributes.forecast.map((item) => {
|
||||
return html`
|
||||
<div class="flex">
|
||||
${item.condition
|
||||
? html`
|
||||
<iron-icon
|
||||
.icon="${weatherIcons[item.condition]}"
|
||||
></iron-icon>
|
||||
`
|
||||
: ""}
|
||||
${!item.templow
|
||||
? html`
|
||||
<div class="main">
|
||||
${this.computeDateTime(item.datetime)}
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
${item.templow
|
||||
? html`
|
||||
<div class="main">
|
||||
${this.computeDate(item.datetime)}
|
||||
</div>
|
||||
<div class="templow">
|
||||
${item.templow} ${this.getUnit("temperature")}
|
||||
</div>
|
||||
`
|
||||
: ""};
|
||||
<div class="temp">
|
||||
${item.temperature} ${this.getUnit("temperature")}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
})}
|
||||
`
|
||||
: ""}
|
||||
${this.stateObj.attributes.attribution
|
||||
? html`
|
||||
<div class="attribution">
|
||||
${this.stateObj.attributes.attribution}
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
iron-icon {
|
||||
color: var(--paper-item-icon-color);
|
||||
}
|
||||
.section {
|
||||
margin: 16px 0 8px 0;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
height: 32px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
.temp,
|
||||
.templow {
|
||||
min-width: 48px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.templow {
|
||||
margin: 0 16px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
.attribution {
|
||||
color: var(--secondary-text-color);
|
||||
text-align: center;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
private computeDate(data) {
|
||||
const date = new Date(data);
|
||||
return date.toLocaleDateString(this.hass.language, {
|
||||
weekday: "long",
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
});
|
||||
}
|
||||
|
||||
private computeDateTime(data) {
|
||||
const date = new Date(data);
|
||||
return date.toLocaleDateString(this.hass.language, {
|
||||
weekday: "long",
|
||||
hour: "numeric",
|
||||
});
|
||||
}
|
||||
|
||||
private getUnit(measure: string): string {
|
||||
const lengthUnit = this.hass.config.unit_system.length || "";
|
||||
switch (measure) {
|
||||
case "air_pressure":
|
||||
return lengthUnit === "km" ? "hPa" : "inHg";
|
||||
case "length":
|
||||
return lengthUnit;
|
||||
case "precipitation":
|
||||
return lengthUnit === "km" ? "mm" : "in";
|
||||
default:
|
||||
return this.hass.config.unit_system[measure] || "";
|
||||
}
|
||||
}
|
||||
|
||||
private windBearingToText(degree: string): string {
|
||||
const degreenum = parseInt(degree, 10);
|
||||
if (isFinite(degreenum)) {
|
||||
// tslint:disable-next-line: no-bitwise
|
||||
return cardinalDirections[(((degreenum + 11.25) / 22.5) | 0) % 16];
|
||||
}
|
||||
return degree;
|
||||
}
|
||||
|
||||
private getWind(speed: string, bearing: string) {
|
||||
if (bearing != null) {
|
||||
const cardinalDirection = this.windBearingToText(bearing);
|
||||
return `${speed} ${this.getUnit("length")}/h (${this.hass.localize(
|
||||
`ui.card.weather.cardinal_direction.${cardinalDirection.toLowerCase()}`
|
||||
) || cardinalDirection})`;
|
||||
}
|
||||
return `${speed} ${this.getUnit("length")}/h`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"more-info-weather": MoreInfoWeather;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user