Ensure forecast temperatures are properly positioned + show em-dash when n/a (#9066)

Co-authored-by: Zack Barett <zackbarett@hey.com>
This commit is contained in:
Philip Allgaier 2022-01-24 17:10:44 +01:00 committed by GitHub
parent 648c02e622
commit 3ddcd2d0f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 146 additions and 119 deletions

View File

@ -436,3 +436,19 @@ export const getWeatherStateIcon = (
return undefined; return undefined;
}; };
const DAY_IN_MILLISECONDS = 86400000;
export const isForecastHourly = (
forecast?: ForecastAttribute[]
): boolean | undefined => {
if (forecast && forecast?.length && forecast?.length > 2) {
const date1 = new Date(forecast[1].datetime);
const date2 = new Date(forecast[2].datetime);
const timeDiff = date2.getTime() - date1.getTime();
return timeDiff < DAY_IN_MILLISECONDS;
}
return undefined;
};

View File

@ -33,7 +33,11 @@ import { formatDateWeekday } from "../../../common/datetime/format_date";
import { formatTimeWeekday } from "../../../common/datetime/format_time"; import { formatTimeWeekday } from "../../../common/datetime/format_time";
import { formatNumber } from "../../../common/number/format_number"; import { formatNumber } from "../../../common/number/format_number";
import "../../../components/ha-svg-icon"; import "../../../components/ha-svg-icon";
import { getWeatherUnit, getWind } from "../../../data/weather"; import {
getWeatherUnit,
getWind,
isForecastHourly,
} from "../../../data/weather";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
const weatherIcons = { const weatherIcons = {
@ -82,6 +86,8 @@ class MoreInfoWeather extends LitElement {
return html``; return html``;
} }
const hourly = isForecastHourly(this.stateObj.attributes.forecast);
return html` return html`
<div class="flex"> <div class="flex">
<ha-svg-icon .path=${mdiThermometer}></ha-svg-icon> <ha-svg-icon .path=${mdiThermometer}></ha-svg-icon>
@ -169,48 +175,49 @@ class MoreInfoWeather extends LitElement {
<div class="section"> <div class="section">
${this.hass.localize("ui.card.weather.forecast")}: ${this.hass.localize("ui.card.weather.forecast")}:
</div> </div>
${this.stateObj.attributes.forecast.map( ${this.stateObj.attributes.forecast.map((item) =>
(item) => html` this._showValue(item.templow) || this._showValue(item.temperature)
<div class="flex"> ? html`<div class="flex">
${item.condition ${item.condition
? html` ? html`
<ha-svg-icon <ha-svg-icon
.path=${weatherIcons[item.condition]} .path=${weatherIcons[item.condition]}
></ha-svg-icon> ></ha-svg-icon>
` `
: ""}
${!this._showValue(item.templow)
? html`
<div class="main">
${formatTimeWeekday(
new Date(item.datetime),
this.hass.locale
)}
</div>
`
: ""}
${this._showValue(item.templow)
? html`
<div class="main">
${formatDateWeekday(
new Date(item.datetime),
this.hass.locale
)}
</div>
<div class="templow">
${formatNumber(item.templow, this.hass.locale)}
${getWeatherUnit(this.hass, "temperature")}
</div>
`
: ""}
<div class="temp">
${this._showValue(item.temperature)
? `${formatNumber(item.temperature, this.hass.locale)}
${getWeatherUnit(this.hass, "temperature")}`
: ""} : ""}
</div> ${hourly
</div> ? html`
` <div class="main">
${formatTimeWeekday(
new Date(item.datetime),
this.hass.locale
)}
</div>
`
: html`
<div class="main">
${formatDateWeekday(
new Date(item.datetime),
this.hass.locale
)}
</div>
`}
<div class="templow">
${this._showValue(item.templow)
? `${formatNumber(item.templow, this.hass.locale)}
${getWeatherUnit(this.hass, "temperature")}`
: hourly
? ""
: "—"}
</div>
<div class="temp">
${this._showValue(item.temperature)
? `${formatNumber(item.temperature, this.hass.locale)}
${getWeatherUnit(this.hass, "temperature")}`
: "—"}
</div>
</div>`
: ""
)} )}
` `
: ""} : ""}

View File

@ -24,6 +24,7 @@ import {
getWeatherStateIcon, getWeatherStateIcon,
getWeatherUnit, getWeatherUnit,
getWind, getWind,
isForecastHourly,
weatherAttrIcons, weatherAttrIcons,
WeatherEntity, WeatherEntity,
weatherSVGStyles, weatherSVGStyles,
@ -177,23 +178,15 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
: undefined; : undefined;
const weather = !forecast || this._config?.show_current !== false; const weather = !forecast || this._config?.show_current !== false;
let hourly: boolean | undefined; const hourly = isForecastHourly(forecast);
let dayNight: boolean | undefined; let dayNight: boolean | undefined;
if (forecast?.length && forecast?.length > 2) { if (hourly) {
const date1 = new Date(forecast[1].datetime); const dateFirst = new Date(forecast![0].datetime);
const date2 = new Date(forecast[2].datetime); const datelast = new Date(forecast![forecast!.length - 1].datetime);
const timeDiff = date2.getTime() - date1.getTime(); const dayDiff = datelast.getTime() - dateFirst.getTime();
hourly = timeDiff < DAY_IN_MILLISECONDS; dayNight = dayDiff > DAY_IN_MILLISECONDS;
if (hourly) {
const dateFirst = new Date(forecast[0].datetime);
const datelast = new Date(forecast[forecast.length - 1].datetime);
const dayDiff = datelast.getTime() - dateFirst.getTime();
dayNight = dayDiff > DAY_IN_MILLISECONDS;
}
} }
const weatherStateIcon = getWeatherStateIcon(stateObj.state, this); const weatherStateIcon = getWeatherStateIcon(stateObj.state, this);
@ -288,69 +281,76 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
${forecast ${forecast
? html` ? html`
<div class="forecast"> <div class="forecast">
${forecast.map( ${forecast.map((item) =>
(item) => html` this._showValue(item.templow) ||
<div> this._showValue(item.temperature)
<div> ? html`
${dayNight <div>
? html` <div>
${new Date(item.datetime).toLocaleDateString( ${dayNight
this.hass!.language, ? html`
{ weekday: "short" } ${new Date(item.datetime).toLocaleDateString(
)} this.hass!.language,
<div class="daynight"> { weekday: "short" }
${item.daytime === undefined || item.daytime )}
? this.hass!.localize("ui.card.weather.day") <div class="daynight">
: this.hass!.localize( ${item.daytime === undefined || item.daytime
"ui.card.weather.night" ? this.hass!.localize(
)}<br /> "ui.card.weather.day"
</div> )
` : this.hass!.localize(
: hourly "ui.card.weather.night"
? html` )}<br />
${formatTime( </div>
new Date(item.datetime), `
this.hass!.locale : hourly
)} ? html`
` ${formatTime(
: html` new Date(item.datetime),
${new Date(item.datetime).toLocaleDateString( this.hass!.locale
this.hass!.language, )}
{ weekday: "short" } `
)} : html`
`} ${new Date(item.datetime).toLocaleDateString(
</div> this.hass!.language,
${item.condition !== undefined && item.condition !== null { weekday: "short" }
? html` )}
<div class="forecast-image-icon"> `}
${getWeatherStateIcon( </div>
item.condition, ${this._showValue(item.condition)
this, ? html`
!(item.daytime || item.daytime === undefined) <div class="forecast-image-icon">
)} ${getWeatherStateIcon(
</div> item.condition!,
` this,
: ""} !(
${item.temperature !== undefined && item.daytime || item.daytime === undefined
item.temperature !== null )
? html` )}
<div class="temp"> </div>
${formatNumber( `
item.temperature, : ""}
this.hass!.locale <div class="temp">
)}° ${this._showValue(item.temperature)
</div> ? html`${formatNumber(
` item.temperature,
: ""} this.hass!.locale
${item.templow !== undefined && item.templow !== null )}°`
? html` : "—"}
<div class="templow"> </div>
${formatNumber(item.templow, this.hass!.locale)}° <div class="templow">
</div> ${this._showValue(item.templow)
` ? html`${formatNumber(
: ""} item.templow!,
</div> this.hass!.locale
` )}°`
: hourly
? ""
: "—"}
</div>
</div>
`
: ""
)} )}
</div> </div>
` `
@ -402,6 +402,10 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
this._veryVeryNarrow = card.offsetWidth < 245; this._veryVeryNarrow = card.offsetWidth < 245;
} }
private _showValue(item?: any): boolean {
return typeof item !== "undefined" && item !== null;
}
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return [ return [
weatherSVGStyles, weatherSVGStyles,