mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
20240104.0 (#19284)
This commit is contained in:
commit
7ce9a937b1
@ -119,7 +119,7 @@
|
||||
"leaflet-draw": "1.0.4",
|
||||
"lit": "2.8.0",
|
||||
"luxon": "3.4.4",
|
||||
"marked": "11.1.0",
|
||||
"marked": "11.1.1",
|
||||
"memoize-one": "6.0.0",
|
||||
"node-vibrant": "3.2.1-alpha.1",
|
||||
"proxy-polyfill": "0.3.2",
|
||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "home-assistant-frontend"
|
||||
version = "20240103.3"
|
||||
version = "20240104.0"
|
||||
license = {text = "Apache-2.0"}
|
||||
description = "The Home Assistant frontend"
|
||||
readme = "README.md"
|
||||
|
@ -47,7 +47,7 @@ export class HaAuthTextField extends HaTextField {
|
||||
// TODO: live() directive needs casting for lit-analyzer
|
||||
// https://github.com/runem/lit-analyzer/pull/91/files
|
||||
// TODO: lit-analyzer labels min/max as (number|string) instead of string
|
||||
return html` <input
|
||||
return html`<input
|
||||
aria-labelledby=${ifDefined(ariaLabelledbyOrUndef)}
|
||||
aria-controls=${ifDefined(ariaControlsOrUndef)}
|
||||
aria-describedby=${ifDefined(ariaDescribedbyOrUndef)}
|
||||
|
@ -254,6 +254,7 @@ export const DOMAINS_INPUT_ROW = [
|
||||
"text",
|
||||
"time",
|
||||
"vacuum",
|
||||
"valve",
|
||||
];
|
||||
|
||||
/** States that we consider "off". */
|
||||
@ -272,6 +273,7 @@ export const DOMAINS_TOGGLE = new Set([
|
||||
"group",
|
||||
"automation",
|
||||
"humidifier",
|
||||
"valve",
|
||||
]);
|
||||
|
||||
/** Domains that have a dynamic entity image / picture. */
|
||||
|
@ -50,6 +50,7 @@ export const FIXED_DOMAIN_STATES = {
|
||||
timer: ["active", "idle", "paused"],
|
||||
update: ["on", "off"],
|
||||
vacuum: ["cleaning", "docked", "error", "idle", "paused", "returning"],
|
||||
valve: ["closed", "closing", "open", "opening"],
|
||||
weather: [
|
||||
"clear-night",
|
||||
"cloudy",
|
||||
|
@ -53,7 +53,7 @@ class MediaUploadButton extends LitElement {
|
||||
${this._uploading > 0
|
||||
? html`
|
||||
<ha-circular-progress
|
||||
size="tiny"
|
||||
size="small"
|
||||
indeterminate
|
||||
area-label="Uploading"
|
||||
slot="icon"
|
||||
|
@ -14,14 +14,20 @@ export const enum ValveEntityFeature {
|
||||
}
|
||||
|
||||
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.state === "open";
|
||||
}
|
||||
|
||||
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.state === "closed";
|
||||
|
@ -326,7 +326,7 @@ class DialogSystemInformation extends LitElement {
|
||||
value = html`
|
||||
<ha-circular-progress
|
||||
indeterminate
|
||||
size="tiny"
|
||||
size="small"
|
||||
></ha-circular-progress>
|
||||
`;
|
||||
} else if (info.type === "failed") {
|
||||
|
@ -247,7 +247,7 @@ export class AssistPipelineRunDebug extends LitElement {
|
||||
}
|
||||
|
||||
// Play audio when we're done.
|
||||
if (updatedRun.stage === "done") {
|
||||
if (updatedRun.stage === "done" && !updatedRun.error) {
|
||||
const url = updatedRun.tts!.tts_output!.url;
|
||||
const audio = new Audio(url);
|
||||
audio.addEventListener("ended", () => {
|
||||
@ -261,7 +261,10 @@ export class AssistPipelineRunDebug extends LitElement {
|
||||
}
|
||||
});
|
||||
audio.play();
|
||||
} else if (updatedRun.stage === "error") {
|
||||
} else if (
|
||||
(updatedRun.stage === "done" && updatedRun.error) ||
|
||||
updatedRun.stage === "error"
|
||||
) {
|
||||
this._finished = true;
|
||||
}
|
||||
},
|
||||
|
@ -90,7 +90,7 @@ const renderProgress = (
|
||||
return html`❌`;
|
||||
}
|
||||
return html`
|
||||
<ha-circular-progress size="tiny" indeterminate></ha-circular-progress>
|
||||
<ha-circular-progress size="small" indeterminate></ha-circular-progress>
|
||||
`;
|
||||
}
|
||||
|
||||
|
@ -335,7 +335,7 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
|
||||
const due = item.due
|
||||
? item.due.includes("T")
|
||||
? new Date(item.due)
|
||||
: endOfDay(new Date(item.due))
|
||||
: endOfDay(new Date(`${item.due}T00:00:00`))
|
||||
: undefined;
|
||||
const today =
|
||||
due && !item.due!.includes("T") && isSameDay(new Date(), due);
|
||||
|
@ -24,6 +24,9 @@ export const turnOnOffEntity = (
|
||||
case "scene":
|
||||
service = "turn_on";
|
||||
break;
|
||||
case "valve":
|
||||
service = turnOn ? "open_valve" : "close_valve";
|
||||
break;
|
||||
default:
|
||||
service = turnOn ? "turn_on" : "turn_off";
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import { stopPropagation } from "../../../../common/dom/stop_propagation";
|
||||
import { createCloseHeading } from "../../../../components/ha-dialog";
|
||||
import "../../../../components/ha-icon";
|
||||
import "../../../../components/ha-select";
|
||||
import "../../../../components/ha-alert";
|
||||
import {
|
||||
fetchConfig,
|
||||
LovelaceConfig,
|
||||
@ -104,8 +105,15 @@ export class HuiDialogSelectView extends LitElement {
|
||||
})}
|
||||
</ha-select>`
|
||||
: ""}
|
||||
${this._config
|
||||
? this._config.views.length > 1
|
||||
${!this._config || (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`
|
||||
<mwc-list dialogInitialFocus>
|
||||
${this._config.views.map(
|
||||
@ -125,8 +133,7 @@ export class HuiDialogSelectView extends LitElement {
|
||||
)}
|
||||
</mwc-list>
|
||||
`
|
||||
: ""
|
||||
: html`<div>No config found.</div>`}
|
||||
: ""}
|
||||
<mwc-button
|
||||
slot="secondaryAction"
|
||||
@click=${this.closeDialog}
|
||||
@ -134,7 +141,11 @@ export class HuiDialogSelectView extends LitElement {
|
||||
>
|
||||
${this.hass!.localize("ui.common.cancel")}
|
||||
</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")}
|
||||
</mwc-button>
|
||||
</ha-dialog>
|
||||
|
@ -250,7 +250,6 @@ class HaPanelProfile extends LitElement {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.content > * {
|
||||
|
@ -60,8 +60,10 @@ class DialogTodoItemEditor extends LitElement {
|
||||
this._checked = entry.status === TodoItemStatus.Completed;
|
||||
this._summary = entry.summary;
|
||||
this._description = entry.description || "";
|
||||
this._due = entry.due ? new Date(entry.due) : undefined;
|
||||
this._hasTime = entry.due?.includes("T") || false;
|
||||
this._due = entry.due
|
||||
? new Date(this._hasTime ? entry.due : `${entry.due}T00:00:00`)
|
||||
: undefined;
|
||||
} else {
|
||||
this._hasTime = false;
|
||||
this._checked = false;
|
||||
|
@ -177,11 +177,20 @@ export class HaStateControlClimateTemperature extends LitElement {
|
||||
|
||||
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`
|
||||
<p class="label">
|
||||
${action
|
||||
${action && action !== "off"
|
||||
? this.hass.formatEntityAttributeValue(this.stateObj, "hvac_action")
|
||||
: this.hass.formatEntityState(this.stateObj)}
|
||||
: isTemperatureDisplayed
|
||||
? this.hass.formatEntityState(this.stateObj)
|
||||
: nothing}
|
||||
</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;
|
||||
}
|
||||
|
||||
@ -373,6 +390,14 @@ export class HaStateControlClimateTemperature extends LitElement {
|
||||
return html`<p class="label"></p>`;
|
||||
}
|
||||
|
||||
private _renderInfo() {
|
||||
return html`
|
||||
<div class="info">
|
||||
${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
get _supportsTargetTemperature() {
|
||||
return (
|
||||
supportsFeature(this.stateObj, ClimateEntityFeature.TARGET_TEMPERATURE) &&
|
||||
@ -447,10 +472,7 @@ export class HaStateControlClimateTemperature extends LitElement {
|
||||
@value-changing=${this._valueChanging}
|
||||
>
|
||||
</ha-control-circular-slider>
|
||||
<div class="info">
|
||||
${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()}
|
||||
</div>
|
||||
${this._renderTemperatureButtons("value")}
|
||||
${this._renderInfo()} ${this._renderTemperatureButtons("value")}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@ -484,9 +506,7 @@ export class HaStateControlClimateTemperature extends LitElement {
|
||||
@high-changing=${this._valueChanging}
|
||||
>
|
||||
</ha-control-circular-slider>
|
||||
<div class="info">
|
||||
${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()}
|
||||
</div>
|
||||
${this._renderInfo()}
|
||||
${this._renderTemperatureButtons(this._selectTargetTemperature, true)}
|
||||
</div>
|
||||
`;
|
||||
@ -497,6 +517,7 @@ export class HaStateControlClimateTemperature extends LitElement {
|
||||
class="container${containerSizeClass}"
|
||||
style=${styleMap({
|
||||
"--state-color": stateColor,
|
||||
"--action-color": actionColor,
|
||||
})}
|
||||
>
|
||||
<ha-control-circular-slider
|
||||
@ -510,9 +531,7 @@ export class HaStateControlClimateTemperature extends LitElement {
|
||||
.disabled=${!active}
|
||||
>
|
||||
</ha-control-circular-slider>
|
||||
<div class="info">
|
||||
${this._renderLabel()} ${this._renderSecondary()}
|
||||
</div>
|
||||
${this._renderInfo()}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
@ -105,11 +105,18 @@ export class HaStateControlHumidifierHumidity extends LitElement {
|
||||
|
||||
const action = this.stateObj.attributes.action;
|
||||
|
||||
const isHumidityDisplayed =
|
||||
(this.stateObj.attributes.current_humidity != null &&
|
||||
this.showCurrentAsPrimary) ||
|
||||
(this._targetHumidity != null && !this.showCurrentAsPrimary);
|
||||
|
||||
return html`
|
||||
<p class="label">
|
||||
${action
|
||||
${action && action !== "off"
|
||||
? this.hass.formatEntityAttributeValue(this.stateObj, "action")
|
||||
: this.hass.formatEntityState(this.stateObj)}
|
||||
: isHumidityDisplayed
|
||||
? this.hass.formatEntityState(this.stateObj)
|
||||
: nothing}
|
||||
</p>
|
||||
`;
|
||||
}
|
||||
@ -144,6 +151,14 @@ export class HaStateControlHumidifierHumidity extends LitElement {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
const stateColor = stateColorCss(this.stateObj);
|
||||
const active = stateActive(this.stateObj);
|
||||
@ -272,10 +295,7 @@ export class HaStateControlHumidifierHumidity extends LitElement {
|
||||
@value-changing=${this._valueChanging}
|
||||
>
|
||||
</ha-control-circular-slider>
|
||||
<div class="info">
|
||||
${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()}
|
||||
</div>
|
||||
${this._renderButtons()}
|
||||
${this._renderInfo()} ${this._renderButtons()}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@ -284,6 +304,7 @@ export class HaStateControlHumidifierHumidity extends LitElement {
|
||||
<div
|
||||
class="container${containerSizeClass}"
|
||||
style=${styleMap({
|
||||
"--state-color": stateColor,
|
||||
"--action-color": actionColor,
|
||||
})}
|
||||
>
|
||||
@ -296,9 +317,7 @@ export class HaStateControlHumidifierHumidity extends LitElement {
|
||||
disabled
|
||||
>
|
||||
</ha-control-circular-slider>
|
||||
<div class="info">
|
||||
${this._renderLabel()} ${this._renderSecondary()}
|
||||
</div>
|
||||
${this._renderInfo()}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
@ -54,7 +54,6 @@ export const stateControlCircularSliderStyle = css`
|
||||
.label.disabled {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
.buttons {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
@ -67,6 +66,9 @@ export const stateControlCircularSliderStyle = css`
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.primary-state {
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.buttons ha-outlined-icon-button {
|
||||
--md-outlined-icon-button-container-width: 48px;
|
||||
@ -77,6 +79,9 @@ export const stateControlCircularSliderStyle = css`
|
||||
.container.md ha-big-number {
|
||||
font-size: 44px;
|
||||
}
|
||||
.container.md .state {
|
||||
font-size: 30px;
|
||||
}
|
||||
.container.md .info {
|
||||
margin-top: 12px;
|
||||
gap: 6px;
|
||||
@ -91,6 +96,9 @@ export const stateControlCircularSliderStyle = css`
|
||||
.container.sm ha-big-number {
|
||||
font-size: 32px;
|
||||
}
|
||||
.container.sm .state {
|
||||
font-size: 26px;
|
||||
}
|
||||
.container.sm .info {
|
||||
margin-top: 12px;
|
||||
font-size: 14px;
|
||||
@ -107,6 +115,9 @@ export const stateControlCircularSliderStyle = css`
|
||||
.container.xs ha-big-number {
|
||||
font-size: 32px;
|
||||
}
|
||||
.container.xs .state {
|
||||
font-size: 16px;
|
||||
}
|
||||
.container.xs .info {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
@ -5020,7 +5020,9 @@
|
||||
"select_view": {
|
||||
"header": "Choose a view",
|
||||
"dashboard_label": "Dashboard",
|
||||
"views_label": "View"
|
||||
"views_label": "View",
|
||||
"no_config": "No config found.",
|
||||
"no_views": "No views in this dashboard."
|
||||
},
|
||||
"suggest_card": {
|
||||
"header": "We created a suggestion for you",
|
||||
|
10
yarn.lock
10
yarn.lock
@ -9679,7 +9679,7 @@ __metadata:
|
||||
luxon: "npm:3.4.4"
|
||||
magic-string: "npm:0.30.5"
|
||||
map-stream: "npm:0.0.7"
|
||||
marked: "npm:11.1.0"
|
||||
marked: "npm:11.1.1"
|
||||
memoize-one: "npm:6.0.0"
|
||||
mocha: "npm:10.2.0"
|
||||
node-vibrant: "npm:3.2.1-alpha.1"
|
||||
@ -11655,12 +11655,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"marked@npm:11.1.0":
|
||||
version: 11.1.0
|
||||
resolution: "marked@npm:11.1.0"
|
||||
"marked@npm:11.1.1":
|
||||
version: 11.1.1
|
||||
resolution: "marked@npm:11.1.1"
|
||||
bin:
|
||||
marked: bin/marked.js
|
||||
checksum: 4636b16283c1963a715e97578d9fd91588b11949276e633a4de53dc408bcdab7b846d2b5c2cf3239f6d2dc8affe5294a0895954b5e3d9562d77301d8847a8915
|
||||
checksum: c2e15a330ac75cca2e12e25aae09985a78ad7e96a84418964dcdd3ee776764a38812dc0e94e9fcbacac43113d1650ca7946f9dc0bab800d72181e56a37e7631e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user