mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Add weather forecast options to more info (#17823)
This commit is contained in:
parent
c3c4bb4421
commit
32472ca627
@ -36,7 +36,9 @@ export const enum WeatherEntityFeature {
|
|||||||
FORECAST_TWICE_DAILY = 4,
|
FORECAST_TWICE_DAILY = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ForecastType = "legacy" | "hourly" | "daily" | "twice_daily";
|
export type ModernForecastType = "hourly" | "daily" | "twice_daily";
|
||||||
|
|
||||||
|
export type ForecastType = ModernForecastType | "legacy";
|
||||||
|
|
||||||
interface ForecastAttribute {
|
interface ForecastAttribute {
|
||||||
temperature: number;
|
temperature: number;
|
||||||
@ -636,7 +638,7 @@ export const getForecast = (
|
|||||||
export const subscribeForecast = (
|
export const subscribeForecast = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entity_id: string,
|
entity_id: string,
|
||||||
forecast_type: "daily" | "hourly" | "twice_daily",
|
forecast_type: ModernForecastType,
|
||||||
callback: (forecastevent: ForecastEvent) => void
|
callback: (forecastevent: ForecastEvent) => void
|
||||||
) =>
|
) =>
|
||||||
hass.connection.subscribeMessage<ForecastEvent>(callback, {
|
hass.connection.subscribeMessage<ForecastEvent>(callback, {
|
||||||
@ -645,6 +647,22 @@ export const subscribeForecast = (
|
|||||||
entity_id,
|
entity_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const getSupportedForecastTypes = (
|
||||||
|
stateObj: HassEntityBase
|
||||||
|
): ModernForecastType[] => {
|
||||||
|
const supported: ModernForecastType[] = [];
|
||||||
|
if (supportsFeature(stateObj, WeatherEntityFeature.FORECAST_DAILY)) {
|
||||||
|
supported.push("daily");
|
||||||
|
}
|
||||||
|
if (supportsFeature(stateObj, WeatherEntityFeature.FORECAST_TWICE_DAILY)) {
|
||||||
|
supported.push("twice_daily");
|
||||||
|
}
|
||||||
|
if (supportsFeature(stateObj, WeatherEntityFeature.FORECAST_HOURLY)) {
|
||||||
|
supported.push("hourly");
|
||||||
|
}
|
||||||
|
return supported;
|
||||||
|
};
|
||||||
|
|
||||||
export const getDefaultForecastType = (stateObj: HassEntityBase) => {
|
export const getDefaultForecastType = (stateObj: HassEntityBase) => {
|
||||||
if (supportsFeature(stateObj, WeatherEntityFeature.FORECAST_DAILY)) {
|
if (supportsFeature(stateObj, WeatherEntityFeature.FORECAST_DAILY)) {
|
||||||
return "daily";
|
return "daily";
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import "@material/mwc-tab-bar/mwc-tab-bar";
|
|
||||||
import "@material/mwc-tab/mwc-tab";
|
|
||||||
import { mdiEyedropper } from "@mdi/js";
|
import { mdiEyedropper } from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import "@material/mwc-tab";
|
||||||
|
import "@material/mwc-tab-bar";
|
||||||
import {
|
import {
|
||||||
mdiEye,
|
mdiEye,
|
||||||
mdiGauge,
|
mdiGauge,
|
||||||
@ -14,14 +16,17 @@ import {
|
|||||||
nothing,
|
nothing,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
import { formatDateWeekdayDay } from "../../../common/datetime/format_date";
|
import { formatDateWeekdayDay } from "../../../common/datetime/format_date";
|
||||||
import { formatTimeWeekday } from "../../../common/datetime/format_time";
|
import { formatTimeWeekday } from "../../../common/datetime/format_time";
|
||||||
import "../../../components/ha-svg-icon";
|
import "../../../components/ha-svg-icon";
|
||||||
import {
|
import {
|
||||||
ForecastEvent,
|
ForecastEvent,
|
||||||
|
ModernForecastType,
|
||||||
WeatherEntity,
|
WeatherEntity,
|
||||||
getDefaultForecastType,
|
getDefaultForecastType,
|
||||||
getForecast,
|
getForecast,
|
||||||
|
getSupportedForecastTypes,
|
||||||
getWind,
|
getWind,
|
||||||
subscribeForecast,
|
subscribeForecast,
|
||||||
weatherIcons,
|
weatherIcons,
|
||||||
@ -36,6 +41,8 @@ class MoreInfoWeather extends LitElement {
|
|||||||
|
|
||||||
@state() private _forecastEvent?: ForecastEvent;
|
@state() private _forecastEvent?: ForecastEvent;
|
||||||
|
|
||||||
|
@state() private _forecastType?: ModernForecastType;
|
||||||
|
|
||||||
@state() private _subscribed?: Promise<() => void>;
|
@state() private _subscribed?: Promise<() => void>;
|
||||||
|
|
||||||
private _unsubscribeForecastEvents() {
|
private _unsubscribeForecastEvents() {
|
||||||
@ -43,25 +50,28 @@ class MoreInfoWeather extends LitElement {
|
|||||||
this._subscribed.then((unsub) => unsub());
|
this._subscribed.then((unsub) => unsub());
|
||||||
this._subscribed = undefined;
|
this._subscribed = undefined;
|
||||||
}
|
}
|
||||||
|
this._forecastEvent = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _subscribeForecastEvents() {
|
private async _subscribeForecastEvents() {
|
||||||
this._unsubscribeForecastEvents();
|
this._unsubscribeForecastEvents();
|
||||||
if (!this.isConnected || !this.hass || !this.stateObj) {
|
if (
|
||||||
|
!this.isConnected ||
|
||||||
|
!this.hass ||
|
||||||
|
!this.stateObj ||
|
||||||
|
!this._forecastType
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const forecastType = getDefaultForecastType(this.stateObj);
|
this._subscribed = subscribeForecast(
|
||||||
if (forecastType) {
|
this.hass!,
|
||||||
this._subscribed = subscribeForecast(
|
this.stateObj!.entity_id,
|
||||||
this.hass!,
|
this._forecastType,
|
||||||
this.stateObj!.entity_id,
|
(event) => {
|
||||||
forecastType,
|
this._forecastEvent = event;
|
||||||
(event) => {
|
}
|
||||||
this._forecastEvent = event;
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public connectedCallback() {
|
public connectedCallback() {
|
||||||
@ -93,10 +103,10 @@ class MoreInfoWeather extends LitElement {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues): void {
|
protected willUpdate(changedProps: PropertyValues): void {
|
||||||
super.updated(changedProps);
|
super.willUpdate(changedProps);
|
||||||
|
|
||||||
if (changedProps.has("stateObj") || !this._subscribed) {
|
if ((changedProps.has("stateObj") || !this._subscribed) && this.stateObj) {
|
||||||
const oldState = changedProps.get("stateObj") as
|
const oldState = changedProps.get("stateObj") as
|
||||||
| WeatherEntity
|
| WeatherEntity
|
||||||
| undefined;
|
| undefined;
|
||||||
@ -104,16 +114,25 @@ class MoreInfoWeather extends LitElement {
|
|||||||
oldState?.entity_id !== this.stateObj?.entity_id ||
|
oldState?.entity_id !== this.stateObj?.entity_id ||
|
||||||
!this._subscribed
|
!this._subscribed
|
||||||
) {
|
) {
|
||||||
|
this._forecastType = getDefaultForecastType(this.stateObj);
|
||||||
this._subscribeForecastEvents();
|
this._subscribeForecastEvents();
|
||||||
}
|
}
|
||||||
|
} else if (changedProps.has("_forecastType")) {
|
||||||
|
this._subscribeForecastEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _supportedForecasts = memoizeOne((stateObj: WeatherEntity) =>
|
||||||
|
getSupportedForecastTypes(stateObj)
|
||||||
|
);
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (!this.hass || !this.stateObj) {
|
if (!this.hass || !this.stateObj) {
|
||||||
return nothing;
|
return nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const supportedForecasts = this._supportedForecasts(this.stateObj);
|
||||||
|
|
||||||
const forecastData = getForecast(
|
const forecastData = getForecast(
|
||||||
this.stateObj.attributes,
|
this.stateObj.attributes,
|
||||||
this._forecastEvent
|
this._forecastEvent
|
||||||
@ -210,6 +229,23 @@ 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>
|
||||||
|
${supportedForecasts.length > 1
|
||||||
|
? html`<mwc-tab-bar
|
||||||
|
.activeIndex=${supportedForecasts.findIndex(
|
||||||
|
(item) => item === this._forecastType
|
||||||
|
)}
|
||||||
|
@MDCTabBar:activated=${this._handleForecastTypeChanged}
|
||||||
|
>
|
||||||
|
${supportedForecasts.map(
|
||||||
|
(forecastType) =>
|
||||||
|
html`<mwc-tab
|
||||||
|
.label=${this.hass!.localize(
|
||||||
|
`ui.card.weather.${forecastType}`
|
||||||
|
)}
|
||||||
|
></mwc-tab>`
|
||||||
|
)}
|
||||||
|
</mwc-tab-bar>`
|
||||||
|
: nothing}
|
||||||
${forecast.map((item) =>
|
${forecast.map((item) =>
|
||||||
this._showValue(item.templow) || this._showValue(item.temperature)
|
this._showValue(item.templow) || this._showValue(item.temperature)
|
||||||
? html`<div class="flex">
|
? html`<div class="flex">
|
||||||
@ -283,12 +319,23 @@ class MoreInfoWeather extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _handleForecastTypeChanged(ev: CustomEvent): void {
|
||||||
|
this._forecastType = this._supportedForecasts(this.stateObj!)[
|
||||||
|
ev.detail.index
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return css`
|
return css`
|
||||||
ha-svg-icon {
|
ha-svg-icon {
|
||||||
color: var(--paper-item-icon-color);
|
color: var(--paper-item-icon-color);
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mwc-tab-bar {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.section {
|
.section {
|
||||||
margin: 16px 0 8px 0;
|
margin: 16px 0 8px 0;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import "@material/mwc-tab";
|
|
||||||
import "@material/mwc-tab-bar";
|
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
import "@material/mwc-button/mwc-button";
|
||||||
import "@material/mwc-list/mwc-list";
|
import "@material/mwc-list/mwc-list";
|
||||||
import "@material/mwc-list/mwc-list-item";
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import "@material/mwc-tab";
|
|
||||||
import "@material/mwc-tab-bar";
|
|
||||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import "../../../components/ha-alert";
|
import "../../../components/ha-alert";
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import "@material/mwc-tab-bar/mwc-tab-bar";
|
|
||||||
import "@material/mwc-tab/mwc-tab";
|
|
||||||
import Fuse from "fuse.js";
|
import Fuse from "fuse.js";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
|
@ -261,6 +261,9 @@
|
|||||||
"forecast_daily": "Forecast daily",
|
"forecast_daily": "Forecast daily",
|
||||||
"forecast_hourly": "Forecast hourly",
|
"forecast_hourly": "Forecast hourly",
|
||||||
"forecast_twice_daily": "Forecast twice daily",
|
"forecast_twice_daily": "Forecast twice daily",
|
||||||
|
"daily": "Daily",
|
||||||
|
"hourly": "Hourly",
|
||||||
|
"twice_daily": "Twice daily",
|
||||||
"high": "High",
|
"high": "High",
|
||||||
"low": "Low"
|
"low": "Low"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user