mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-11 19:36:35 +00:00
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:
parent
648c02e622
commit
3ddcd2d0f6
@ -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;
|
||||||
|
};
|
||||||
|
@ -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>`
|
||||||
|
: ""
|
||||||
)}
|
)}
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user