Convert more-info-weather to LitElement (#4073)

* Convert more-info-weather to LitElement

* address comments

* add shouldUpdate
This commit is contained in:
Ian Richardson 2019-10-21 13:04:08 -05:00 committed by GitHub
parent 0078b48e3c
commit be678b02c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 288 additions and 235 deletions

View File

@ -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);

View 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;
}
}