diff --git a/src/dialogs/more-info/const.ts b/src/dialogs/more-info/const.ts index e75fd38516d8..6dcad0610812 100644 --- a/src/dialogs/more-info/const.ts +++ b/src/dialogs/more-info/const.ts @@ -31,6 +31,7 @@ export const DOMAINS_WITH_NEW_MORE_INFO = [ "switch", "valve", "water_heater", + "weather", ]; /** Domains with full height more info dialog */ export const DOMAINS_FULL_HEIGHT_MORE_INFO = ["update"]; diff --git a/src/dialogs/more-info/controls/more-info-weather.ts b/src/dialogs/more-info/controls/more-info-weather.ts index 6dfaeb3ed4df..b0ae0b1136f1 100644 --- a/src/dialogs/more-info/controls/more-info-weather.ts +++ b/src/dialogs/more-info/controls/more-info-weather.ts @@ -1,18 +1,13 @@ import "@material/mwc-tab"; import "@material/mwc-tab-bar"; -import { - mdiEye, - mdiGauge, - mdiThermometer, - mdiWaterPercent, - mdiWeatherWindy, -} from "@mdi/js"; +import { mdiEye, mdiGauge, mdiWaterPercent, mdiWeatherWindy } from "@mdi/js"; import type { CSSResultGroup, PropertyValues } from "lit"; import { LitElement, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; -import { formatDateWeekdayDay } from "../../../common/datetime/format_date"; -import { formatTimeWeekday } from "../../../common/datetime/format_time"; +import { formatDateWeekdayShort } from "../../../common/datetime/format_date"; +import { formatTime } from "../../../common/datetime/format_time"; +import { formatNumber } from "../../../common/number/format_number"; import "../../../components/ha-svg-icon"; import type { ForecastEvent, @@ -23,11 +18,17 @@ import { getDefaultForecastType, getForecast, getSupportedForecastTypes, + getSecondaryWeatherAttribute, + getWeatherStateIcon, + getWeatherUnit, getWind, subscribeForecast, - weatherIcons, + weatherSVGStyles, } from "../../../data/weather"; import type { HomeAssistant } from "../../../types"; +import "../../../components/ha-relative-time"; +import "../../../components/ha-state-icon"; +import "../../../components/ha-badge"; @customElement("more-info-weather") class MoreInfoWeather extends LitElement { @@ -133,66 +134,134 @@ class MoreInfoWeather extends LitElement { this.stateObj.attributes, this._forecastEvent ); - const forecast = forecastData?.forecast; + const forecast = forecastData?.forecast.slice(0, 6); const hourly = forecastData?.type === "hourly"; const dayNight = forecastData?.type === "twice_daily"; + const weatherStateIcon = getWeatherStateIcon(this.stateObj.state, this); + return html` - ${this._showValue(this.stateObj.attributes.temperature) - ? html` -
- -
- ${this.hass.localize("ui.card.weather.attributes.temperature")} -
-
- ${this.hass.formatEntityAttributeValue( - this.stateObj, - "temperature" - )} -
+
+
+ ${weatherStateIcon || + html` + + `} +
+
+
+
+ ${this.hass.formatEntityState(this.stateObj)}
- ` - : ""} - ${this._showValue(this.stateObj.attributes.pressure) - ? html` -
- -
- ${this.hass.localize("ui.card.weather.attributes.air_pressure")} -
+
+ + +
+
+ + ${this.hass.localize( + "ui.dialogs.more_info_control.last_changed" + )}: + + +
+
+ + ${this.hass.localize( + "ui.dialogs.more_info_control.last_updated" + )}: + + +
+
+
+
+
+
+
+ ${this.stateObj.attributes.temperature !== undefined && + this.stateObj.attributes.temperature !== null + ? html` + ${formatNumber( + this.stateObj.attributes.temperature, + this.hass.locale + )} ${getWeatherUnit( + this.hass.config, + this.stateObj, + "temperature" + )} + ` + : html` `} +
+
+ ${getSecondaryWeatherAttribute( + this.hass, + this.stateObj, + forecast! + )} +
+
+
+
+
+ ${this._showValue(this.stateObj.attributes.pressure) + ? html` +
${this.hass.formatEntityAttributeValue( this.stateObj, "pressure" )}
-
- ` - : ""} - ${this._showValue(this.stateObj.attributes.humidity) - ? html` -
- -
- ${this.hass.localize("ui.card.weather.attributes.humidity")} -
-
- ${this.hass.formatEntityAttributeValue( - this.stateObj, - "humidity" + ` + : ""} + ${this._showValue(this.stateObj.attributes.humidity) + ? html` + -
- ` - : ""} - ${this._showValue(this.stateObj.attributes.wind_speed) - ? html` -
- -
- ${this.hass.localize("ui.card.weather.attributes.wind_speed")} -
+ > + +
+ ${this.hass.formatEntityAttributeValue( + this.stateObj, + "humidity" + )} +
+ + ` + : ""} + ${this._showValue(this.stateObj.attributes.wind_speed) + ? html` +
${getWind( this.hass, @@ -201,25 +270,24 @@ class MoreInfoWeather extends LitElement { this.stateObj.attributes.wind_bearing )}
-
- ` - : ""} - ${this._showValue(this.stateObj.attributes.visibility) - ? html` -
- -
- ${this.hass.localize("ui.card.weather.attributes.visibility")} -
+ ` + : ""} + ${this._showValue(this.stateObj.attributes.visibility) + ? html` +
${this.hass.formatEntityAttributeValue( this.stateObj, "visibility" )}
-
- ` - : ""} + ` + : ""} +
${forecast ? html`
@@ -242,67 +310,81 @@ class MoreInfoWeather extends LitElement { )} ` : nothing} - ${forecast.map((item) => - this._showValue(item.templow) || this._showValue(item.temperature) - ? html`
- ${item.condition - ? html` - - ` - : ""} -
- ${dayNight - ? html` - ${formatDateWeekdayDay( - new Date(item.datetime), - this.hass!.locale, - this.hass!.config - )} - (${item.is_daytime !== false - ? this.hass!.localize("ui.card.weather.day") - : this.hass!.localize("ui.card.weather.night")}) - ` - : hourly +
+ ${forecast.map((item) => + this._showValue(item.templow) || + this._showValue(item.temperature) + ? html` +
+
+ ${dayNight + ? html` + ${formatDateWeekdayShort( + new Date(item.datetime), + this.hass!.locale, + this.hass!.config + )} +
+ ${item.is_daytime !== false + ? this.hass!.localize("ui.card.weather.day") + : this.hass!.localize( + "ui.card.weather.night" + )}
+
+ ` + : hourly + ? html` + ${formatTime( + new Date(item.datetime), + this.hass!.locale, + this.hass!.config + )} + ` + : html` + ${formatDateWeekdayShort( + new Date(item.datetime), + this.hass!.locale, + this.hass!.config + )} + `} +
+ ${this._showValue(item.condition) ? html` - ${formatTimeWeekday( - new Date(item.datetime), - this.hass!.locale, - this.hass!.config - )} +
+ ${getWeatherStateIcon( + item.condition!, + this, + !( + item.is_daytime || + item.is_daytime === undefined + ) + )} +
` - : html` - ${formatDateWeekdayDay( - new Date(item.datetime), - this.hass!.locale, - this.hass!.config - )} - `} -
-
- ${this._showValue(item.templow) - ? this.hass.formatEntityAttributeValue( - this.stateObj!, - "templow", - item.templow - ) - : hourly - ? "" - : "—"} -
-
- ${this._showValue(item.temperature) - ? this.hass.formatEntityAttributeValue( - this.stateObj!, - "temperature", - item.temperature - ) - : "—"} -
-
` - : "" - )} + : ""} +
+ ${this._showValue(item.temperature) + ? html`${formatNumber( + item.temperature, + this.hass!.locale + )}°` + : "—"} +
+
+ ${this._showValue(item.templow) + ? html`${formatNumber( + item.templow!, + this.hass!.locale + )}°` + : hourly + ? "" + : "—"} +
+
+ ` + : "" + )} +
` : ""} ${this.stateObj.attributes.attribution @@ -322,56 +404,163 @@ class MoreInfoWeather extends LitElement { } static get styles(): CSSResultGroup { - return css` - ha-svg-icon { - color: var(--paper-item-icon-color); - margin-left: 8px; - margin-inline-start: 8px; - margin-inline-end: initial; - } + return [ + weatherSVGStyles, + css` + ha-svg-icon { + color: var(--paper-item-icon-color); + } - mwc-tab-bar { - margin-bottom: 4px; - } + mwc-tab-bar { + margin-bottom: 4px; + } - .section { - margin: 16px 0 8px 0; - font-size: 1.2em; - } + .section { + margin: 16px 0 8px 0; + font-size: 1.2em; + } - .flex { - display: flex; - height: 32px; - align-items: center; - } - .flex > div:last-child { - direction: ltr; - } + .badges { + display: flex; + justify-content: center; + flex-wrap: wrap; + } - .main { - flex: 1; - margin-left: 24px; - margin-inline-start: 24px; - margin-inline-end: initial; - } + .badges ha-badge { + margin: 8px 8px; + } - .temp, - .templow { - min-width: 48px; - text-align: right; - direction: ltr; - } + .attribution { + text-align: center; + margin-top: 16px; + } - .templow { - margin: 0 16px; - color: var(--secondary-text-color); - } + .time-ago, + .attribute { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } - .attribution { - color: var(--secondary-text-color); - text-align: center; - } - `; + .attribution, + .templow, + .daynight, + .attribute, + .time-ago { + color: var(--secondary-text-color); + } + + .content { + display: flex; + flex-wrap: nowrap; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + } + + .icon-image { + display: flex; + align-items: center; + min-width: 64px; + margin-right: 16px; + margin-inline-end: 16px; + margin-inline-start: initial; + } + + .icon-image > * { + flex: 0 0 64px; + height: 64px; + } + + .weather-icon { + --mdc-icon-size: 64px; + } + + .info { + display: flex; + justify-content: space-between; + flex-grow: 1; + overflow: hidden; + } + + .temp-attribute { + text-align: var(--float-end); + } + + .temp-attribute .temp { + position: relative; + margin-right: 24px; + direction: ltr; + } + + .temp-attribute .temp span { + position: absolute; + font-size: 24px; + top: 1px; + } + + .state, + .temp-attribute .temp { + font-size: 28px; + line-height: 1.2; + } + + .attribute { + font-size: 14px; + line-height: 1; + } + + .name-state { + overflow: hidden; + padding-right: 12px; + padding-inline-end: 12px; + padding-inline-start: initial; + width: 100%; + } + + .state { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .forecast { + display: flex; + justify-content: space-around; + padding-top: 16px; + } + + .forecast > div { + text-align: center; + } + + .forecast .icon, + .forecast .temp { + margin: 4px 0; + } + + .forecast .temp { + font-size: 16px; + } + + .forecast-image-icon { + padding-top: 4px; + padding-bottom: 4px; + display: flex; + justify-content: center; + } + + .forecast-image-icon > * { + width: 40px; + height: 40px; + --mdc-icon-size: 40px; + } + + .forecast-icon { + --mdc-icon-size: 40px; + } + `, + ]; } private _showValue(item: number | string | undefined): boolean {