mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-02 14:07:55 +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