20240104.0 (#19284)

This commit is contained in:
Bram Kragten 2024-01-04 17:48:13 +01:00 committed by GitHub
commit 7ce9a937b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 124 additions and 46 deletions

View File

@ -119,7 +119,7 @@
"leaflet-draw": "1.0.4", "leaflet-draw": "1.0.4",
"lit": "2.8.0", "lit": "2.8.0",
"luxon": "3.4.4", "luxon": "3.4.4",
"marked": "11.1.0", "marked": "11.1.1",
"memoize-one": "6.0.0", "memoize-one": "6.0.0",
"node-vibrant": "3.2.1-alpha.1", "node-vibrant": "3.2.1-alpha.1",
"proxy-polyfill": "0.3.2", "proxy-polyfill": "0.3.2",

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "home-assistant-frontend" name = "home-assistant-frontend"
version = "20240103.3" version = "20240104.0"
license = {text = "Apache-2.0"} license = {text = "Apache-2.0"}
description = "The Home Assistant frontend" description = "The Home Assistant frontend"
readme = "README.md" readme = "README.md"

View File

@ -47,7 +47,7 @@ export class HaAuthTextField extends HaTextField {
// TODO: live() directive needs casting for lit-analyzer // TODO: live() directive needs casting for lit-analyzer
// https://github.com/runem/lit-analyzer/pull/91/files // https://github.com/runem/lit-analyzer/pull/91/files
// TODO: lit-analyzer labels min/max as (number|string) instead of string // TODO: lit-analyzer labels min/max as (number|string) instead of string
return html` <input return html`<input
aria-labelledby=${ifDefined(ariaLabelledbyOrUndef)} aria-labelledby=${ifDefined(ariaLabelledbyOrUndef)}
aria-controls=${ifDefined(ariaControlsOrUndef)} aria-controls=${ifDefined(ariaControlsOrUndef)}
aria-describedby=${ifDefined(ariaDescribedbyOrUndef)} aria-describedby=${ifDefined(ariaDescribedbyOrUndef)}

View File

@ -254,6 +254,7 @@ export const DOMAINS_INPUT_ROW = [
"text", "text",
"time", "time",
"vacuum", "vacuum",
"valve",
]; ];
/** States that we consider "off". */ /** States that we consider "off". */
@ -272,6 +273,7 @@ export const DOMAINS_TOGGLE = new Set([
"group", "group",
"automation", "automation",
"humidifier", "humidifier",
"valve",
]); ]);
/** Domains that have a dynamic entity image / picture. */ /** Domains that have a dynamic entity image / picture. */

View File

@ -50,6 +50,7 @@ export const FIXED_DOMAIN_STATES = {
timer: ["active", "idle", "paused"], timer: ["active", "idle", "paused"],
update: ["on", "off"], update: ["on", "off"],
vacuum: ["cleaning", "docked", "error", "idle", "paused", "returning"], vacuum: ["cleaning", "docked", "error", "idle", "paused", "returning"],
valve: ["closed", "closing", "open", "opening"],
weather: [ weather: [
"clear-night", "clear-night",
"cloudy", "cloudy",

View File

@ -53,7 +53,7 @@ class MediaUploadButton extends LitElement {
${this._uploading > 0 ${this._uploading > 0
? html` ? html`
<ha-circular-progress <ha-circular-progress
size="tiny" size="small"
indeterminate indeterminate
area-label="Uploading" area-label="Uploading"
slot="icon" slot="icon"

View File

@ -14,14 +14,20 @@ export const enum ValveEntityFeature {
} }
export function isFullyOpen(stateObj: ValveEntity) { export function isFullyOpen(stateObj: ValveEntity) {
if (stateObj.attributes.current_position !== undefined) { if (
stateObj.attributes.current_position !== undefined &&
stateObj.attributes.current_position !== null
) {
return stateObj.attributes.current_position === 100; return stateObj.attributes.current_position === 100;
} }
return stateObj.state === "open"; return stateObj.state === "open";
} }
export function isFullyClosed(stateObj: ValveEntity) { export function isFullyClosed(stateObj: ValveEntity) {
if (stateObj.attributes.current_position !== undefined) { if (
stateObj.attributes.current_position !== undefined &&
stateObj.attributes.current_position !== null
) {
return stateObj.attributes.current_position === 0; return stateObj.attributes.current_position === 0;
} }
return stateObj.state === "closed"; return stateObj.state === "closed";

View File

@ -326,7 +326,7 @@ class DialogSystemInformation extends LitElement {
value = html` value = html`
<ha-circular-progress <ha-circular-progress
indeterminate indeterminate
size="tiny" size="small"
></ha-circular-progress> ></ha-circular-progress>
`; `;
} else if (info.type === "failed") { } else if (info.type === "failed") {

View File

@ -247,7 +247,7 @@ export class AssistPipelineRunDebug extends LitElement {
} }
// Play audio when we're done. // Play audio when we're done.
if (updatedRun.stage === "done") { if (updatedRun.stage === "done" && !updatedRun.error) {
const url = updatedRun.tts!.tts_output!.url; const url = updatedRun.tts!.tts_output!.url;
const audio = new Audio(url); const audio = new Audio(url);
audio.addEventListener("ended", () => { audio.addEventListener("ended", () => {
@ -261,7 +261,10 @@ export class AssistPipelineRunDebug extends LitElement {
} }
}); });
audio.play(); audio.play();
} else if (updatedRun.stage === "error") { } else if (
(updatedRun.stage === "done" && updatedRun.error) ||
updatedRun.stage === "error"
) {
this._finished = true; this._finished = true;
} }
}, },

View File

@ -90,7 +90,7 @@ const renderProgress = (
return html``; return html``;
} }
return html` return html`
<ha-circular-progress size="tiny" indeterminate></ha-circular-progress> <ha-circular-progress size="small" indeterminate></ha-circular-progress>
`; `;
} }

View File

@ -335,7 +335,7 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
const due = item.due const due = item.due
? item.due.includes("T") ? item.due.includes("T")
? new Date(item.due) ? new Date(item.due)
: endOfDay(new Date(item.due)) : endOfDay(new Date(`${item.due}T00:00:00`))
: undefined; : undefined;
const today = const today =
due && !item.due!.includes("T") && isSameDay(new Date(), due); due && !item.due!.includes("T") && isSameDay(new Date(), due);

View File

@ -24,6 +24,9 @@ export const turnOnOffEntity = (
case "scene": case "scene":
service = "turn_on"; service = "turn_on";
break; break;
case "valve":
service = turnOn ? "open_valve" : "close_valve";
break;
default: default:
service = turnOn ? "turn_on" : "turn_off"; service = turnOn ? "turn_on" : "turn_off";
} }

View File

@ -8,6 +8,7 @@ import { stopPropagation } from "../../../../common/dom/stop_propagation";
import { createCloseHeading } from "../../../../components/ha-dialog"; import { createCloseHeading } from "../../../../components/ha-dialog";
import "../../../../components/ha-icon"; import "../../../../components/ha-icon";
import "../../../../components/ha-select"; import "../../../../components/ha-select";
import "../../../../components/ha-alert";
import { import {
fetchConfig, fetchConfig,
LovelaceConfig, LovelaceConfig,
@ -104,8 +105,15 @@ export class HuiDialogSelectView extends LitElement {
})} })}
</ha-select>` </ha-select>`
: ""} : ""}
${this._config ${!this._config || (this._config.views || []).length < 1
? this._config.views.length > 1 ? html`<ha-alert alert-type="error"
>${this.hass.localize(
this._config
? "ui.panel.lovelace.editor.select_view.no_views"
: "ui.panel.lovelace.editor.select_view.no_config"
)}</ha-alert
>`
: this._config.views.length > 1
? html` ? html`
<mwc-list dialogInitialFocus> <mwc-list dialogInitialFocus>
${this._config.views.map( ${this._config.views.map(
@ -125,8 +133,7 @@ export class HuiDialogSelectView extends LitElement {
)} )}
</mwc-list> </mwc-list>
` `
: "" : ""}
: html`<div>No config found.</div>`}
<mwc-button <mwc-button
slot="secondaryAction" slot="secondaryAction"
@click=${this.closeDialog} @click=${this.closeDialog}
@ -134,7 +141,11 @@ export class HuiDialogSelectView extends LitElement {
> >
${this.hass!.localize("ui.common.cancel")} ${this.hass!.localize("ui.common.cancel")}
</mwc-button> </mwc-button>
<mwc-button slot="primaryAction" @click=${this._selectView}> <mwc-button
slot="primaryAction"
.disabled=${!this._config || (this._config.views || []).length < 1}
@click=${this._selectView}
>
${this._params.actionLabel || this.hass!.localize("ui.common.move")} ${this._params.actionLabel || this.hass!.localize("ui.common.move")}
</mwc-button> </mwc-button>
</ha-dialog> </ha-dialog>

View File

@ -250,7 +250,6 @@ class HaPanelProfile extends LitElement {
max-width: 600px; max-width: 600px;
margin: 0 auto; margin: 0 auto;
padding-bottom: env(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom);
overflow: hidden;
} }
.content > * { .content > * {

View File

@ -60,8 +60,10 @@ class DialogTodoItemEditor extends LitElement {
this._checked = entry.status === TodoItemStatus.Completed; this._checked = entry.status === TodoItemStatus.Completed;
this._summary = entry.summary; this._summary = entry.summary;
this._description = entry.description || ""; this._description = entry.description || "";
this._due = entry.due ? new Date(entry.due) : undefined;
this._hasTime = entry.due?.includes("T") || false; this._hasTime = entry.due?.includes("T") || false;
this._due = entry.due
? new Date(this._hasTime ? entry.due : `${entry.due}T00:00:00`)
: undefined;
} else { } else {
this._hasTime = false; this._hasTime = false;
this._checked = false; this._checked = false;

View File

@ -177,11 +177,20 @@ export class HaStateControlClimateTemperature extends LitElement {
const action = this.stateObj.attributes.hvac_action; const action = this.stateObj.attributes.hvac_action;
const isTemperatureDisplayed =
(this.stateObj.attributes.current_temperature != null &&
this.showCurrentAsPrimary) ||
((this._supportsTargetTemperature ||
this._supportsTargetTemperatureRange) &&
!this.showCurrentAsPrimary);
return html` return html`
<p class="label"> <p class="label">
${action ${action && action !== "off"
? this.hass.formatEntityAttributeValue(this.stateObj, "hvac_action") ? this.hass.formatEntityAttributeValue(this.stateObj, "hvac_action")
: this.hass.formatEntityState(this.stateObj)} : isTemperatureDisplayed
? this.hass.formatEntityState(this.stateObj)
: nothing}
</p> </p>
`; `;
} }
@ -315,6 +324,14 @@ export class HaStateControlClimateTemperature extends LitElement {
`; `;
} }
if (this.stateObj.state !== UNAVAILABLE) {
return html`
<p class="primary-state">
${this.hass.formatEntityState(this.stateObj)}
</p>
`;
}
return nothing; return nothing;
} }
@ -373,6 +390,14 @@ export class HaStateControlClimateTemperature extends LitElement {
return html`<p class="label"></p>`; return html`<p class="label"></p>`;
} }
private _renderInfo() {
return html`
<div class="info">
${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()}
</div>
`;
}
get _supportsTargetTemperature() { get _supportsTargetTemperature() {
return ( return (
supportsFeature(this.stateObj, ClimateEntityFeature.TARGET_TEMPERATURE) && supportsFeature(this.stateObj, ClimateEntityFeature.TARGET_TEMPERATURE) &&
@ -447,10 +472,7 @@ export class HaStateControlClimateTemperature extends LitElement {
@value-changing=${this._valueChanging} @value-changing=${this._valueChanging}
> >
</ha-control-circular-slider> </ha-control-circular-slider>
<div class="info"> ${this._renderInfo()} ${this._renderTemperatureButtons("value")}
${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()}
</div>
${this._renderTemperatureButtons("value")}
</div> </div>
`; `;
} }
@ -484,9 +506,7 @@ export class HaStateControlClimateTemperature extends LitElement {
@high-changing=${this._valueChanging} @high-changing=${this._valueChanging}
> >
</ha-control-circular-slider> </ha-control-circular-slider>
<div class="info"> ${this._renderInfo()}
${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()}
</div>
${this._renderTemperatureButtons(this._selectTargetTemperature, true)} ${this._renderTemperatureButtons(this._selectTargetTemperature, true)}
</div> </div>
`; `;
@ -497,6 +517,7 @@ export class HaStateControlClimateTemperature extends LitElement {
class="container${containerSizeClass}" class="container${containerSizeClass}"
style=${styleMap({ style=${styleMap({
"--state-color": stateColor, "--state-color": stateColor,
"--action-color": actionColor,
})} })}
> >
<ha-control-circular-slider <ha-control-circular-slider
@ -510,9 +531,7 @@ export class HaStateControlClimateTemperature extends LitElement {
.disabled=${!active} .disabled=${!active}
> >
</ha-control-circular-slider> </ha-control-circular-slider>
<div class="info"> ${this._renderInfo()}
${this._renderLabel()} ${this._renderSecondary()}
</div>
</div> </div>
`; `;
} }

View File

@ -105,11 +105,18 @@ export class HaStateControlHumidifierHumidity extends LitElement {
const action = this.stateObj.attributes.action; const action = this.stateObj.attributes.action;
const isHumidityDisplayed =
(this.stateObj.attributes.current_humidity != null &&
this.showCurrentAsPrimary) ||
(this._targetHumidity != null && !this.showCurrentAsPrimary);
return html` return html`
<p class="label"> <p class="label">
${action ${action && action !== "off"
? this.hass.formatEntityAttributeValue(this.stateObj, "action") ? this.hass.formatEntityAttributeValue(this.stateObj, "action")
: this.hass.formatEntityState(this.stateObj)} : isHumidityDisplayed
? this.hass.formatEntityState(this.stateObj)
: nothing}
</p> </p>
`; `;
} }
@ -144,6 +151,14 @@ export class HaStateControlHumidifierHumidity extends LitElement {
return this._renderTarget(this._targetHumidity!, "big"); return this._renderTarget(this._targetHumidity!, "big");
} }
if (this.stateObj.state !== UNAVAILABLE) {
return html`
<p class="primary-state">
${this.hass.formatEntityState(this.stateObj)}
</p>
`;
}
return nothing; return nothing;
} }
@ -225,6 +240,14 @@ export class HaStateControlHumidifierHumidity extends LitElement {
`; `;
} }
private _renderInfo() {
return html`
<div class="info">
${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()}
</div>
`;
}
protected render() { protected render() {
const stateColor = stateColorCss(this.stateObj); const stateColor = stateColorCss(this.stateObj);
const active = stateActive(this.stateObj); const active = stateActive(this.stateObj);
@ -272,10 +295,7 @@ export class HaStateControlHumidifierHumidity extends LitElement {
@value-changing=${this._valueChanging} @value-changing=${this._valueChanging}
> >
</ha-control-circular-slider> </ha-control-circular-slider>
<div class="info"> ${this._renderInfo()} ${this._renderButtons()}
${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()}
</div>
${this._renderButtons()}
</div> </div>
`; `;
} }
@ -284,6 +304,7 @@ export class HaStateControlHumidifierHumidity extends LitElement {
<div <div
class="container${containerSizeClass}" class="container${containerSizeClass}"
style=${styleMap({ style=${styleMap({
"--state-color": stateColor,
"--action-color": actionColor, "--action-color": actionColor,
})} })}
> >
@ -296,9 +317,7 @@ export class HaStateControlHumidifierHumidity extends LitElement {
disabled disabled
> >
</ha-control-circular-slider> </ha-control-circular-slider>
<div class="info"> ${this._renderInfo()}
${this._renderLabel()} ${this._renderSecondary()}
</div>
</div> </div>
`; `;
} }

View File

@ -54,7 +54,6 @@ export const stateControlCircularSliderStyle = css`
.label.disabled { .label.disabled {
color: var(--secondary-text-color); color: var(--secondary-text-color);
} }
.buttons { .buttons {
position: absolute; position: absolute;
bottom: 10px; bottom: 10px;
@ -67,6 +66,9 @@ export const stateControlCircularSliderStyle = css`
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.primary-state {
font-size: 36px;
}
.buttons ha-outlined-icon-button { .buttons ha-outlined-icon-button {
--md-outlined-icon-button-container-width: 48px; --md-outlined-icon-button-container-width: 48px;
@ -77,6 +79,9 @@ export const stateControlCircularSliderStyle = css`
.container.md ha-big-number { .container.md ha-big-number {
font-size: 44px; font-size: 44px;
} }
.container.md .state {
font-size: 30px;
}
.container.md .info { .container.md .info {
margin-top: 12px; margin-top: 12px;
gap: 6px; gap: 6px;
@ -91,6 +96,9 @@ export const stateControlCircularSliderStyle = css`
.container.sm ha-big-number { .container.sm ha-big-number {
font-size: 32px; font-size: 32px;
} }
.container.sm .state {
font-size: 26px;
}
.container.sm .info { .container.sm .info {
margin-top: 12px; margin-top: 12px;
font-size: 14px; font-size: 14px;
@ -107,6 +115,9 @@ export const stateControlCircularSliderStyle = css`
.container.xs ha-big-number { .container.xs ha-big-number {
font-size: 32px; font-size: 32px;
} }
.container.xs .state {
font-size: 16px;
}
.container.xs .info { .container.xs .info {
margin-top: 12px; margin-top: 12px;
} }

View File

@ -5020,7 +5020,9 @@
"select_view": { "select_view": {
"header": "Choose a view", "header": "Choose a view",
"dashboard_label": "Dashboard", "dashboard_label": "Dashboard",
"views_label": "View" "views_label": "View",
"no_config": "No config found.",
"no_views": "No views in this dashboard."
}, },
"suggest_card": { "suggest_card": {
"header": "We created a suggestion for you", "header": "We created a suggestion for you",

View File

@ -9679,7 +9679,7 @@ __metadata:
luxon: "npm:3.4.4" luxon: "npm:3.4.4"
magic-string: "npm:0.30.5" magic-string: "npm:0.30.5"
map-stream: "npm:0.0.7" map-stream: "npm:0.0.7"
marked: "npm:11.1.0" marked: "npm:11.1.1"
memoize-one: "npm:6.0.0" memoize-one: "npm:6.0.0"
mocha: "npm:10.2.0" mocha: "npm:10.2.0"
node-vibrant: "npm:3.2.1-alpha.1" node-vibrant: "npm:3.2.1-alpha.1"
@ -11655,12 +11655,12 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"marked@npm:11.1.0": "marked@npm:11.1.1":
version: 11.1.0 version: 11.1.1
resolution: "marked@npm:11.1.0" resolution: "marked@npm:11.1.1"
bin: bin:
marked: bin/marked.js marked: bin/marked.js
checksum: 4636b16283c1963a715e97578d9fd91588b11949276e633a4de53dc408bcdab7b846d2b5c2cf3239f6d2dc8affe5294a0895954b5e3d9562d77301d8847a8915 checksum: c2e15a330ac75cca2e12e25aae09985a78ad7e96a84418964dcdd3ee776764a38812dc0e94e9fcbacac43113d1650ca7946f9dc0bab800d72181e56a37e7631e
languageName: node languageName: node
linkType: hard linkType: hard