From 5e279405c725462ccc2c0d623804d8516cfe1cd6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Dec 2023 20:32:43 -0500 Subject: [PATCH 001/361] Update typescript-eslint monorepo to v6.16.0 (#19174) --- package.json | 4 +- yarn.lock | 121 ++++++++++++++++++++++++++------------------------- 2 files changed, 63 insertions(+), 62 deletions(-) diff --git a/package.json b/package.json index d8b369de1280..339896248684 100644 --- a/package.json +++ b/package.json @@ -184,8 +184,8 @@ "@types/tar": "6.1.10", "@types/ua-parser-js": "0.7.39", "@types/webspeechapi": "0.0.29", - "@typescript-eslint/eslint-plugin": "6.15.0", - "@typescript-eslint/parser": "6.15.0", + "@typescript-eslint/eslint-plugin": "6.16.0", + "@typescript-eslint/parser": "6.16.0", "@web/dev-server": "0.1.38", "@web/dev-server-rollup": "0.4.1", "babel-loader": "9.1.3", diff --git a/yarn.lock b/yarn.lock index 66ab497b9976..e3f41249e572 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4566,15 +4566,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:6.15.0": - version: 6.15.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.15.0" +"@typescript-eslint/eslint-plugin@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.16.0" dependencies: "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:6.15.0" - "@typescript-eslint/type-utils": "npm:6.15.0" - "@typescript-eslint/utils": "npm:6.15.0" - "@typescript-eslint/visitor-keys": "npm:6.15.0" + "@typescript-eslint/scope-manager": "npm:6.16.0" + "@typescript-eslint/type-utils": "npm:6.16.0" + "@typescript-eslint/utils": "npm:6.16.0" + "@typescript-eslint/visitor-keys": "npm:6.16.0" debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" ignore: "npm:^5.2.4" @@ -4587,44 +4587,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 9020370c5e89b52b65ed2373c755d4b70f57ec7ebcf02d3e2f323f31ec81717af110d8e5f903b189b71e0a952f042e0fe2b637e77959c3102907efed4ba55512 + checksum: 4bedce948ac3c20492a59813ee5d4f1f2306310857864dfaac2736f6c38e18785002c36844fd64c9fbdf3059fc390b29412be105fd7a118177f1eeeb1eb533f7 languageName: node linkType: hard -"@typescript-eslint/parser@npm:6.15.0": - version: 6.15.0 - resolution: "@typescript-eslint/parser@npm:6.15.0" +"@typescript-eslint/parser@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/parser@npm:6.16.0" dependencies: - "@typescript-eslint/scope-manager": "npm:6.15.0" - "@typescript-eslint/types": "npm:6.15.0" - "@typescript-eslint/typescript-estree": "npm:6.15.0" - "@typescript-eslint/visitor-keys": "npm:6.15.0" + "@typescript-eslint/scope-manager": "npm:6.16.0" + "@typescript-eslint/types": "npm:6.16.0" + "@typescript-eslint/typescript-estree": "npm:6.16.0" + "@typescript-eslint/visitor-keys": "npm:6.16.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: fdd1f584e5068216c36a01e40750950ef309b36a522f6ecde36931690558a319960a702b4b4a806f335fb28ca99f8a07bb206571141550aaab1f6f40066f6605 + checksum: 3d941ce345dc2ce29957e2110957662873d514b094b8939923c3281d858c11cd1f9058db862644afe14f68d087770f39a0a1f9e523a2013ed5d2fdf3421b34d0 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.15.0": - version: 6.15.0 - resolution: "@typescript-eslint/scope-manager@npm:6.15.0" +"@typescript-eslint/scope-manager@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/scope-manager@npm:6.16.0" dependencies: - "@typescript-eslint/types": "npm:6.15.0" - "@typescript-eslint/visitor-keys": "npm:6.15.0" - checksum: 168d783c06a99784362e2eaaa56396b31716ee785779707ef984c2abb3e822c56440473efc6580cb8b84b2da508731ad184a00b3618bc7f3f93d8243804f2fcf + "@typescript-eslint/types": "npm:6.16.0" + "@typescript-eslint/visitor-keys": "npm:6.16.0" + checksum: 3360aae4b85f5c31d20ad48d771cc09a6f8f6b1811b00d94f06e55b5a09c610ac75631b1c4edecb3bec682d41351b87e7d14d42bee84aa032064d0e13463035b languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.15.0": - version: 6.15.0 - resolution: "@typescript-eslint/type-utils@npm:6.15.0" +"@typescript-eslint/type-utils@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/type-utils@npm:6.16.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:6.15.0" - "@typescript-eslint/utils": "npm:6.15.0" + "@typescript-eslint/typescript-estree": "npm:6.16.0" + "@typescript-eslint/utils": "npm:6.16.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.0.1" peerDependencies: @@ -4632,59 +4632,60 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 8dabb355f09f57de8b46d726ad95a57593e5b87427dee5182afecb490624424afec02b69a27018b352dcb5f930eb391cb8cdc12cd60a93231d4f04e63e2f2c0b + checksum: 5964b87a87252bed278a248eb568902babd7c34defd3af8c3df371926d96aec716f33f1dc14bde170e93f73ed1b0af6e591e647853d0f33f378e2c7b3b73fc5b languageName: node linkType: hard -"@typescript-eslint/types@npm:6.15.0": - version: 6.15.0 - resolution: "@typescript-eslint/types@npm:6.15.0" - checksum: d55de64d532c9016c922cc36b86ab661d7d64d942057486a0bca7a7db07fade95c3de59bfe364bc76ab538fb979ca2e4e6744c3acf8919a2d61e73cc7f544363 +"@typescript-eslint/types@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/types@npm:6.16.0" + checksum: 236ca318c2440c95068e5d4d147e2bfed62447775e18695e21c8ca04a341a74d01c37ed2b417629b7bf2fb91ad4fd5e2a6570215d16fc24dd1507ce6973b4e22 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.15.0": - version: 6.15.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.15.0" +"@typescript-eslint/typescript-estree@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.16.0" dependencies: - "@typescript-eslint/types": "npm:6.15.0" - "@typescript-eslint/visitor-keys": "npm:6.15.0" + "@typescript-eslint/types": "npm:6.16.0" + "@typescript-eslint/visitor-keys": "npm:6.16.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" + minimatch: "npm:9.0.3" semver: "npm:^7.5.4" ts-api-utils: "npm:^1.0.1" peerDependenciesMeta: typescript: optional: true - checksum: 920f7f3bfe463a9da943e1a686b7f13ac802a5e33be52f39ac711aa53a1e274dbe173b41bba05581c560fabfc3e1fadcfd81ab53a036afe25fb1a76651fcad7a + checksum: 8e1ef03ecabaf3791b11240a51217836dbb74850e458258db77ac5eab5508cd9c63fb671924993d1e7654718c0c857c3550d51ecba0845fe489d143bb858e1b1 languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.15.0": - version: 6.15.0 - resolution: "@typescript-eslint/utils@npm:6.15.0" +"@typescript-eslint/utils@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/utils@npm:6.16.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" "@types/json-schema": "npm:^7.0.12" "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:6.15.0" - "@typescript-eslint/types": "npm:6.15.0" - "@typescript-eslint/typescript-estree": "npm:6.15.0" + "@typescript-eslint/scope-manager": "npm:6.16.0" + "@typescript-eslint/types": "npm:6.16.0" + "@typescript-eslint/typescript-estree": "npm:6.16.0" semver: "npm:^7.5.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 7895240933ad28295508f8c4286a8b905550a35eda83a11ecf9511e53078e0af07e75a1872f1bc757f165b41fdc84616ea97c1e2e3bf80cff985935f25596228 + checksum: 84dd02f7c8e47fae699cc222da5cbea08b28c6e1cc7827860430bc86c2a17ee3f86e198a4356902b95930f85785aa662266ea9c476f69bf80c6a5f648e55f9f4 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.15.0": - version: 6.15.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.15.0" +"@typescript-eslint/visitor-keys@npm:6.16.0": + version: 6.16.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.16.0" dependencies: - "@typescript-eslint/types": "npm:6.15.0" + "@typescript-eslint/types": "npm:6.16.0" eslint-visitor-keys: "npm:^3.4.1" - checksum: 4641a829485f67a5d9d3558aa0d152e5ab57b468cfd9653168ce9a141e1f051730669a024505183b64f7a7e5d8f62533af4ebd4ad7366b551390461e9c45ec18 + checksum: 19e559f14ea0092585a374b8c5f1aca9b6b271fc23909d9857de9cf71a1e1d3abc0afd237e9c02d7a5fbdfe8e3be7853cf9fedf40a6f16bac3495cb7f4e67982 languageName: node linkType: hard @@ -9618,8 +9619,8 @@ __metadata: "@types/tar": "npm:6.1.10" "@types/ua-parser-js": "npm:0.7.39" "@types/webspeechapi": "npm:0.0.29" - "@typescript-eslint/eslint-plugin": "npm:6.15.0" - "@typescript-eslint/parser": "npm:6.15.0" + "@typescript-eslint/eslint-plugin": "npm:6.16.0" + "@typescript-eslint/parser": "npm:6.16.0" "@vaadin/combo-box": "npm:24.3.2" "@vaadin/vaadin-themable-mixin": "npm:24.3.2" "@vibrant/color": "npm:3.2.1-alpha.1" @@ -11859,21 +11860,21 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^5.0.1": - version: 5.1.6 - resolution: "minimatch@npm:5.1.6" +"minimatch@npm:9.0.3, minimatch@npm:^9.0.1": + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" dependencies: brace-expansion: "npm:^2.0.1" - checksum: 126b36485b821daf96d33b5c821dac600cc1ab36c87e7a532594f9b1652b1fa89a1eebcaad4dff17c764dce1a7ac1531327f190fed5f97d8f6e5f889c116c429 + checksum: c81b47d28153e77521877649f4bab48348d10938df9e8147a58111fe00ef89559a2938de9f6632910c4f7bf7bb5cd81191a546167e58d357f0cfb1e18cecc1c5 languageName: node linkType: hard -"minimatch@npm:^9.0.1": - version: 9.0.3 - resolution: "minimatch@npm:9.0.3" +"minimatch@npm:^5.0.1": + version: 5.1.6 + resolution: "minimatch@npm:5.1.6" dependencies: brace-expansion: "npm:^2.0.1" - checksum: c81b47d28153e77521877649f4bab48348d10938df9e8147a58111fe00ef89559a2938de9f6632910c4f7bf7bb5cd81191a546167e58d357f0cfb1e18cecc1c5 + checksum: 126b36485b821daf96d33b5c821dac600cc1ab36c87e7a532594f9b1652b1fa89a1eebcaad4dff17c764dce1a7ac1531327f190fed5f97d8f6e5f889c116c429 languageName: node linkType: hard From c25baf25ad137f09a54ced2b7408b02417f4e72f Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Fri, 29 Dec 2023 18:41:10 +0100 Subject: [PATCH 002/361] Exclude hidden entities from scenes (#19179) --- src/panels/config/scene/ha-scene-editor.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/panels/config/scene/ha-scene-editor.ts b/src/panels/config/scene/ha-scene-editor.ts index ea28abb08b1a..da9817835151 100644 --- a/src/panels/config/scene/ha-scene-editor.ts +++ b/src/panels/config/scene/ha-scene-editor.ts @@ -513,6 +513,7 @@ export class HaSceneEditor extends SubscribeMixin( if ( !entity.device_id || entity.entity_category || + entity.hidden_by || SCENE_IGNORED_DOMAINS.includes(computeDomain(entity.entity_id)) ) { continue; From 442cce15741d0fa19665c60192e7b4684f052695 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 29 Dec 2023 18:56:15 +0100 Subject: [PATCH 003/361] Fix play media action not shown (#19187) --- src/panels/config/automation/add-automation-element-dialog.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index fdf1d97f4086..f05d9ef3fe3c 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -198,7 +198,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { ): ListItem[] => { if (type === "action" && isService(group)) { const result = this._services(localize, services, manifests, group); - if (group === "service_media_player") { + if (group === `${SERVICE_PREFIX}media_player`) { result.unshift(this._convertToItem("play_media", {}, type, localize)); } return result; From cb568d005e8f2b635475dafc373798153e82ba5c Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 29 Dec 2023 18:59:11 +0100 Subject: [PATCH 004/361] dont allow UI editor when templates are used in repeat (#19188) --- .../types/ha-automation-action-repeat.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/panels/config/automation/action/types/ha-automation-action-repeat.ts b/src/panels/config/automation/action/types/ha-automation-action-repeat.ts index 890133d25019..becc0f6f75b0 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-repeat.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-repeat.ts @@ -1,4 +1,4 @@ -import { css, CSSResultGroup, html, LitElement } from "lit"; +import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit"; import { customElement, property } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../../../common/dom/fire_event"; @@ -12,6 +12,7 @@ import type { ActionElement } from "../ha-automation-action-row"; import type { LocalizeFunc } from "../../../../../common/translations/localize"; import "../../../../../components/ha-form/ha-form"; import type { SchemaUnion } from "../../../../../components/ha-form/types"; +import { hasTemplate } from "../../../../../common/string/has-template"; const OPTIONS = ["count", "while", "until", "for_each"] as const; @@ -31,6 +32,20 @@ export class HaRepeatAction extends LitElement implements ActionElement { return { repeat: { count: 2, sequence: [] } }; } + public willUpdate(changedProperties: PropertyValues) { + if (!changedProperties.has("action")) { + return; + } + // Check for templates in action. If found, revert to YAML mode. + if (this.action && hasTemplate(this.action)) { + fireEvent( + this, + "ui-mode-not-available", + Error(this.hass.localize("ui.errors.config.no_template_editor_support")) + ); + } + } + private _schema = memoizeOne( (localize: LocalizeFunc, type: string, reOrderMode: boolean) => [ @@ -92,7 +107,7 @@ export class HaRepeatAction extends LitElement implements ActionElement { this.reOrderMode ); const data = { ...action, type }; - return html` Date: Fri, 29 Dec 2023 20:45:51 +0100 Subject: [PATCH 005/361] Use username in example on empty automation page (#19189) --- src/components/media-player/ha-browse-media-tts.ts | 2 +- src/panels/config/automation/ha-automation-picker.ts | 3 ++- src/panels/config/automation/manual-automation-editor.ts | 2 +- src/translations/en.json | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/media-player/ha-browse-media-tts.ts b/src/components/media-player/ha-browse-media-tts.ts index 39e36b60b7b5..cb10b053c421 100644 --- a/src/components/media-player/ha-browse-media-tts.ts +++ b/src/components/media-player/ha-browse-media-tts.ts @@ -62,7 +62,7 @@ class BrowseMediaTTS extends LitElement { this.hass.localize( "ui.components.media-browser.tts.example_message", { - name: this.hass.user?.name || "", + name: this.hass.user?.name || "Alice", } )} > diff --git a/src/panels/config/automation/ha-automation-picker.ts b/src/panels/config/automation/ha-automation-picker.ts index a29a88d6a35c..7fe54ec1f818 100644 --- a/src/panels/config/automation/ha-automation-picker.ts +++ b/src/panels/config/automation/ha-automation-picker.ts @@ -342,7 +342,8 @@ class HaAutomationPicker extends LitElement {

${this.hass.localize( - "ui.panel.config.automation.picker.empty_text_2" + "ui.panel.config.automation.picker.empty_text_2", + { user: this.hass.user?.name || "Alice" } )}

${this.hass.localize( "ui.panel.config.automation.editor.conditions.description", - { user: this.hass.user?.name } + { user: this.hass.user?.name || "Alice" } )}

` : nothing} diff --git a/src/translations/en.json b/src/translations/en.json index 0209a3ffb70b..76eab13fdbe3 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2386,7 +2386,7 @@ }, "empty_header": "Start automating", "empty_text_1": "Automations make Home Assistant automatically respond to things happening in and around your home.", - "empty_text_2": "Automations connect triggers to actions in a ''when trigger then action'' fashion with optional conditions. For example: ''When the sun sets and if Alice is home, then turn on the lights''." + "empty_text_2": "Automations connect triggers to actions in a ''when trigger then action'' fashion with optional conditions. For example: ''When the sun sets and if {user} is home, then turn on the lights''." }, "dialog_new": { "header": "Create automation", From 7e6d974438cb75c74c8ab97955060842f75f1c99 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Sat, 30 Dec 2023 14:08:01 +0100 Subject: [PATCH 006/361] Fix iteration index when displaying changed variables (#19184) --- src/components/trace/ha-trace-path-details.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/trace/ha-trace-path-details.ts b/src/components/trace/ha-trace-path-details.ts index f87d9006ef4e..bd827283728b 100644 --- a/src/components/trace/ha-trace-path-details.ts +++ b/src/components/trace/ha-trace-path-details.ts @@ -212,7 +212,7 @@ export class HaTracePathDetails extends LitElement {
${data.map( (trace, idx) => html` - ${idx > 0 + ${data.length > 1 ? html`

${this.hass!.localize( "ui.panel.config.automation.trace.path.iteration", From 3c2fed504123cad2df38976d3b341f1e0b68ab89 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Sat, 30 Dec 2023 18:08:24 +0100 Subject: [PATCH 007/361] Improve message when an automation step was not executed (#19185) * Improve message when an automation step was not executed * Use step instead of node --- src/components/trace/ha-trace-path-details.ts | 4 ++-- src/translations/en.json | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/trace/ha-trace-path-details.ts b/src/components/trace/ha-trace-path-details.ts index bd827283728b..33a73af3ed45 100644 --- a/src/components/trace/ha-trace-path-details.ts +++ b/src/components/trace/ha-trace-path-details.ts @@ -133,7 +133,7 @@ export class HaTracePathDetails extends LitElement { if (result?.enabled === false) { return html`${this.hass!.localize( - "ui.panel.config.automation.trace.path.disabled_node" + "ui.panel.config.automation.trace.path.disabled_step" )}`; } @@ -240,7 +240,7 @@ export class HaTracePathDetails extends LitElement { if (index === -1) { return html`

${this.hass!.localize( - "ui.panel.config.automation.trace.path.node_not_tracked" + "ui.panel.config.automation.trace.path.step_not_executed" )}
`; } diff --git a/src/translations/en.json b/src/translations/en.json index 76eab13fdbe3..b78aebb34507 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3114,15 +3114,15 @@ "blueprint_config": "Blueprint Config" }, "path": { - "choose": "Select a node on the left for more information.", + "choose": "Select a step on the left for more information.", "default_action_executed": "The default action was executed because no options matched.", - "no_further_execution": "This node was not executed and so no further trace information is available.", - "disabled_node": "This node was disabled and skipped during execution so no further trace information is available.", + "no_further_execution": "This step was not executed and so no further trace information is available.", + "disabled_step": "This step was disabled and skipped during execution so no further trace information is available.", "iteration": "Iteration {number}", "executed": "Executed: {time}", "error": "Error: {error}", "result": "Result:", - "node_not_tracked": "Node not tracked.", + "step_not_executed": "This step was not executed.", "no_logbook_entries": "No Logbook entries found for this step.", "no_variables_changed": "No variables changed", "unable_to_find_config": "Unable to find config" From c584f830719b0d081f3672bb75200d4cee2cdeba Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Sat, 30 Dec 2023 18:16:54 +0100 Subject: [PATCH 008/361] Fix display of variables tab when automation step not executed (#19186) Co-authored-by: Bram Kragten --- src/components/trace/ha-trace-path-details.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/components/trace/ha-trace-path-details.ts b/src/components/trace/ha-trace-path-details.ts index 33a73af3ed45..514377e61f4f 100644 --- a/src/components/trace/ha-trace-path-details.ts +++ b/src/components/trace/ha-trace-path-details.ts @@ -208,6 +208,14 @@ export class HaTracePathDetails extends LitElement { const paths = this.trace.trace; const data: ActionTraceStep[] = paths[this.selected.path]; + if (data === undefined) { + return html`
+ ${this.hass!.localize( + "ui.panel.config.automation.trace.path.step_not_executed" + )} +
`; + } + return html`
${data.map( From 721ec8e559c5c35d4d78470367dc4afb86e110aa Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Sat, 30 Dec 2023 09:37:50 -0800 Subject: [PATCH 009/361] Localize some strings in integration panel (#19200) --- .../config/integrations/dialog-add-integration.ts | 10 +++++++--- src/translations/en.json | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/panels/config/integrations/dialog-add-integration.ts b/src/panels/config/integrations/dialog-add-integration.ts index 757f23160276..65edfbfccf67 100644 --- a/src/panels/config/integrations/dialog-add-integration.ts +++ b/src/panels/config/integrations/dialog-add-integration.ts @@ -340,7 +340,9 @@ class AddIntegrationDialog extends LitElement { !("integrations" in integration) && !this._flowsInProgress?.length ) { - return "What type of device is it?"; + return this.hass.localize( + "ui.panel.config.integrations.what_device_type" + ); } if ( integration && @@ -348,9 +350,11 @@ class AddIntegrationDialog extends LitElement { !("integrations" in integration) && this._flowsInProgress?.length ) { - return "Want to add these discovered devices?"; + return this.hass.localize( + "ui.panel.config.integrations.confirm_add_discovered" + ); } - return "What do you want to add?"; + return this.hass.localize("ui.panel.config.integrations.what_to_add"); } private _renderIntegration( diff --git a/src/translations/en.json b/src/translations/en.json index b78aebb34507..be18b476ad29 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3799,6 +3799,9 @@ "add_zwave_js_device": "Add Z-Wave device", "add_zha_device": "Add Zigbee device", "add_matter_device": "Add Matter device", + "what_device_type": "What type of device is it?", + "what_to_add": "What do you want to add?", + "confirm_add_discovered": "Want to add these discovered devices?", "disable": { "show_disabled": "Show disabled integrations", "disabled_integrations": "{number} disabled", From ee57f26415d087bbffbb61321335d1778df262d8 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Sat, 30 Dec 2023 18:39:21 +0100 Subject: [PATCH 010/361] Sort domains correctly, scroll to top on back (#19197) --- .../add-automation-element-dialog.ts | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index f05d9ef3fe3c..b96283a61dd8 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -254,31 +254,29 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { return []; } const result: ListItem[] = []; - Object.keys(services) - .sort() - .forEach((domain) => { - const manifest = manifests[domain]; - if ( - (type === undefined && - manifest?.integration_type === "entity" && - !ENTITY_DOMAINS_OTHER.has(domain)) || - (type === "helper" && manifest?.integration_type === "helper") || - (type === "other" && - (ENTITY_DOMAINS_OTHER.has(domain) || - !["helper", "entity"].includes( - manifest?.integration_type || "" - ))) - ) { - result.push({ - group: true, - icon: domainIcon(domain), - key: `${SERVICE_PREFIX}${domain}`, - name: domainToName(localize, domain, manifest), - description: "", - }); - } - }); - return result; + Object.keys(services).forEach((domain) => { + const manifest = manifests[domain]; + if ( + (type === undefined && + manifest?.integration_type === "entity" && + !ENTITY_DOMAINS_OTHER.has(domain)) || + (type === "helper" && manifest?.integration_type === "helper") || + (type === "other" && + (ENTITY_DOMAINS_OTHER.has(domain) || + !["helper", "entity"].includes(manifest?.integration_type || ""))) + ) { + result.push({ + group: true, + icon: domainIcon(domain), + key: `${SERVICE_PREFIX}${domain}`, + name: domainToName(localize, domain, manifest), + description: "", + }); + } + }); + return result.sort((a, b) => + stringCompare(a.name, b.name, this.hass.locale.language) + ); } ); @@ -515,6 +513,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { } private _back() { + this._dialog!.scrollToPos(0, 0); if (this._filter) { this._filter = ""; return; From fe18f70e51c76b7da0a67d6ffd2696eb9f408e0c Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Sat, 30 Dec 2023 18:40:01 +0100 Subject: [PATCH 011/361] Only make count field template (#19198) --- .../types/ha-automation-action-repeat.ts | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/panels/config/automation/action/types/ha-automation-action-repeat.ts b/src/panels/config/automation/action/types/ha-automation-action-repeat.ts index becc0f6f75b0..7a1ad36e8156 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-repeat.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-repeat.ts @@ -1,4 +1,4 @@ -import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit"; +import { css, CSSResultGroup, html, LitElement } from "lit"; import { customElement, property } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../../../common/dom/fire_event"; @@ -9,10 +9,10 @@ import type { HomeAssistant } from "../../../../../types"; import "../ha-automation-action"; import type { ActionElement } from "../ha-automation-action-row"; +import { isTemplate } from "../../../../../common/string/has-template"; import type { LocalizeFunc } from "../../../../../common/translations/localize"; import "../../../../../components/ha-form/ha-form"; import type { SchemaUnion } from "../../../../../components/ha-form/types"; -import { hasTemplate } from "../../../../../common/string/has-template"; const OPTIONS = ["count", "while", "until", "for_each"] as const; @@ -32,22 +32,13 @@ export class HaRepeatAction extends LitElement implements ActionElement { return { repeat: { count: 2, sequence: [] } }; } - public willUpdate(changedProperties: PropertyValues) { - if (!changedProperties.has("action")) { - return; - } - // Check for templates in action. If found, revert to YAML mode. - if (this.action && hasTemplate(this.action)) { - fireEvent( - this, - "ui-mode-not-available", - Error(this.hass.localize("ui.errors.config.no_template_editor_support")) - ); - } - } - private _schema = memoizeOne( - (localize: LocalizeFunc, type: string, reOrderMode: boolean) => + ( + localize: LocalizeFunc, + type: string, + reOrderMode: boolean, + template: boolean + ) => [ { name: "type", @@ -68,7 +59,9 @@ export class HaRepeatAction extends LitElement implements ActionElement { { name: "count", required: true, - selector: { number: { mode: "box", min: 1 } }, + selector: template + ? ({ template: {} } as const) + : ({ number: { mode: "box", min: 1 } } as const), }, ] as const) : []), @@ -104,7 +97,10 @@ export class HaRepeatAction extends LitElement implements ActionElement { const schema = this._schema( this.hass.localize, type ?? "count", - this.reOrderMode + this.reOrderMode, + "count" in action && typeof action.count === "string" + ? isTemplate(action.count) + : false ); const data = { ...action, type }; return html` Date: Sat, 30 Dec 2023 20:21:33 +0100 Subject: [PATCH 012/361] Allow to clear due date (#19201) --- src/components/ha-date-input.ts | 18 ++++++++++++++++-- src/components/ha-dialog-date-picker.ts | 14 ++++++++++++++ src/data/todo.ts | 8 ++++---- src/panels/todo/dialog-todo-item-editor.ts | 17 +++++++++++------ src/translations/en.json | 3 ++- 5 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/components/ha-date-input.ts b/src/components/ha-date-input.ts index d3b5a0607eb3..d4d9922639d9 100644 --- a/src/components/ha-date-input.ts +++ b/src/components/ha-date-input.ts @@ -18,7 +18,8 @@ export interface datePickerDialogParams { max?: string; locale?: string; firstWeekday?: number; - onChange: (value: string) => void; + canClear?: boolean; + onChange: (value: string | undefined) => void; } const showDatePickerDialog = ( @@ -49,6 +50,8 @@ export class HaDateInput extends LitElement { @property() public helper?: string; + @property({ type: Boolean }) public canClear?: boolean; + render() { return html` this._valueChanged(value), locale: this.locale.language, firstWeekday: firstWeekdayIndex(this.locale), }); } - private _valueChanged(value: string) { + private _keyDown(ev: KeyboardEvent) { + if (!this.canClear) { + return; + } + if (["Backspace", "Delete"].includes(ev.key)) { + this._valueChanged(undefined); + } + } + + private _valueChanged(value: string | undefined) { if (this.value !== value) { this.value = value; fireEvent(this, "change"); diff --git a/src/components/ha-dialog-date-picker.ts b/src/components/ha-dialog-date-picker.ts index 2422754cfb15..b71e063ae410 100644 --- a/src/components/ha-dialog-date-picker.ts +++ b/src/components/ha-dialog-date-picker.ts @@ -50,6 +50,15 @@ export class HaDialogDatePicker extends LitElement { @datepicker-value-updated=${this._valueChanged} .firstDayOfWeek=${this._params.firstWeekday} > + ${this._params.canClear + ? html` + ${this.hass.localize("ui.dialogs.date-picker.clear")} + ` + : nothing} ${this.hass.localize("ui.dialogs.date-picker.today")} @@ -66,6 +75,11 @@ export class HaDialogDatePicker extends LitElement { this._value = ev.detail.value; } + private _clear() { + this._params?.onChange(undefined); + this.closeDialog(); + } + private _setToday() { const today = new Date(); this._value = format(today, "yyyy-MM-dd"); diff --git a/src/data/todo.ts b/src/data/todo.ts index e4f99090776b..9af8ef0f4cc6 100644 --- a/src/data/todo.ts +++ b/src/data/todo.ts @@ -18,8 +18,8 @@ export interface TodoItem { uid: string; summary: string; status: TodoItemStatus; - description?: string; - due?: string; + description?: string | null; + due?: string | null; } export const enum TodoListEntityFeature { @@ -83,9 +83,9 @@ export const updateItem = ( item: item.uid, rename: item.summary, status: item.status, - description: item.description || undefined, + description: item.description || null, due_datetime: item.due?.includes("T") ? item.due : undefined, - due_date: item.due?.includes("T") ? undefined : item.due || undefined, + due_date: item.due?.includes("T") ? undefined : item.due || null, }, { entity_id } ); diff --git a/src/panels/todo/dialog-todo-item-editor.ts b/src/panels/todo/dialog-todo-item-editor.ts index 5206bfe8a877..c81b9e4dbec3 100644 --- a/src/panels/todo/dialog-todo-item-editor.ts +++ b/src/panels/todo/dialog-todo-item-editor.ts @@ -161,7 +161,8 @@ class DialogTodoItemEditor extends LitElement { .value=${dueDate} .locale=${this.hass.locale} .disabled=${!canUpdate} - @value-changed=${this._endDateChanged} + @value-changed=${this._dueDateChanged} + canClear > ${this._todoListSupportsFeature( TodoListEntityFeature.SET_DUE_DATETIME_ON_ITEM @@ -170,7 +171,7 @@ class DialogTodoItemEditor extends LitElement { .value=${dueTime} .locale=${this.hass.locale} .disabled=${!canUpdate} - @value-changed=${this._endTimeChanged} + @value-changed=${this._dueTimeChanged} >` : nothing}
@@ -259,12 +260,16 @@ class DialogTodoItemEditor extends LitElement { this._description = ev.target.value; } - private _endDateChanged(ev: CustomEvent) { + private _dueDateChanged(ev: CustomEvent) { + if (!ev.detail.value) { + this._due = undefined; + return; + } const time = this._due ? this._formatTime(this._due) : undefined; this._due = this._parseDate(`${ev.detail.value}${time ? `T${time}` : ""}`); } - private _endTimeChanged(ev: CustomEvent) { + private _dueTimeChanged(ev: CustomEvent) { this._hasTime = true; this._due = this._parseDate( `${this._formatDate(this._due || new Date())}T${ev.detail.value}` @@ -320,13 +325,13 @@ class DialogTodoItemEditor extends LitElement { TodoListEntityFeature.SET_DESCRIPTION_ON_ITEM ) ? // backend should accept null to clear the field, but it doesn't now - " " + null : undefined), due: this._due ? this._hasTime ? this._due.toISOString() : this._formatDate(this._due) - : undefined, + : null, status: this._checked ? TodoItemStatus.Completed : TodoItemStatus.NeedsAction, diff --git a/src/translations/en.json b/src/translations/en.json index be18b476ad29..0039d9926f56 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -1009,7 +1009,8 @@ "crop_image": "Picture to crop" }, "date-picker": { - "today": "Today" + "today": "Today", + "clear": "Clear" }, "more_info_control": { "dismiss": "Dismiss dialog", From e7cc842be46a734f44bbeb560449adefc3a709f7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Dec 2023 21:05:23 -0500 Subject: [PATCH 013/361] Update dependency rollup-plugin-visualizer to v5.12.0 (#19204) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 339896248684..232e4b0beaf5 100644 --- a/package.json +++ b/package.json @@ -229,7 +229,7 @@ "rollup": "2.79.1", "rollup-plugin-string": "3.0.0", "rollup-plugin-terser": "7.0.2", - "rollup-plugin-visualizer": "5.11.0", + "rollup-plugin-visualizer": "5.12.0", "serve-handler": "6.1.5", "sinon": "17.0.1", "source-map-url": "0.4.1", diff --git a/yarn.lock b/yarn.lock index e3f41249e572..08117eab574a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9701,7 +9701,7 @@ __metadata: rollup: "npm:2.79.1" rollup-plugin-string: "npm:3.0.0" rollup-plugin-terser: "npm:7.0.2" - rollup-plugin-visualizer: "npm:5.11.0" + rollup-plugin-visualizer: "npm:5.12.0" rrule: "npm:2.8.1" serve-handler: "npm:6.1.5" sinon: "npm:17.0.1" @@ -13846,9 +13846,9 @@ __metadata: languageName: node linkType: hard -"rollup-plugin-visualizer@npm:5.11.0": - version: 5.11.0 - resolution: "rollup-plugin-visualizer@npm:5.11.0" +"rollup-plugin-visualizer@npm:5.12.0": + version: 5.12.0 + resolution: "rollup-plugin-visualizer@npm:5.12.0" dependencies: open: "npm:^8.4.0" picomatch: "npm:^2.3.1" @@ -13861,7 +13861,7 @@ __metadata: optional: true bin: rollup-plugin-visualizer: dist/bin/cli.js - checksum: 947238aa22706a47a4d3e8ce616855f0e5cb969ed9f61b9a268eaede0a86f461ecb38e27b4e6bf00f4b5e3f63677667f65e0d4af89a659a5160f74add1f192bb + checksum: 47358feb672291d6edcfd94197577c192a84c24cb644119425dae8241fb6f5a52556efd0c501f38b276c07534642a80c0885ef681babb474e83c7b5a3b475b84 languageName: node linkType: hard From bf5c5bc46fa79f6f20127dab55a26bef19b34e97 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Dec 2023 21:06:30 -0500 Subject: [PATCH 014/361] Update dependency open to v10.0.2 (#19206) --- package.json | 2 +- yarn.lock | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 232e4b0beaf5..be8b0f961a1c 100644 --- a/package.json +++ b/package.json @@ -223,7 +223,7 @@ "map-stream": "0.0.7", "mocha": "10.2.0", "object-hash": "3.0.0", - "open": "10.0.1", + "open": "10.0.2", "pinst": "3.0.0", "prettier": "3.1.1", "rollup": "2.79.1", diff --git a/yarn.lock b/yarn.lock index 08117eab574a..812ddda50de9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7228,13 +7228,13 @@ __metadata: languageName: node linkType: hard -"default-browser@npm:^5.2.0": - version: 5.2.0 - resolution: "default-browser@npm:5.2.0" +"default-browser@npm:^5.2.1": + version: 5.2.1 + resolution: "default-browser@npm:5.2.1" dependencies: bundle-name: "npm:^4.1.0" default-browser-id: "npm:^5.0.0" - checksum: 95530de0dca75892b4382d086f42bd798f54a1e25eab748e84e1b64566568b1a02cf1eccfb60a8fbab303d72c09938c2d34e0b38e57d85efd24f13a60d2de802 + checksum: afab7eff7b7f5f7a94d9114d1ec67273d3fbc539edf8c0f80019879d53aa71e867303c6f6d7cffeb10a6f3cfb59d4f963dba3f9c96830b4540cc7339a1bf9840 languageName: node linkType: hard @@ -9690,7 +9690,7 @@ __metadata: mocha: "npm:10.2.0" node-vibrant: "npm:3.2.1-alpha.1" object-hash: "npm:3.0.0" - open: "npm:10.0.1" + open: "npm:10.0.2" pinst: "npm:3.0.0" prettier: "npm:3.1.1" proxy-polyfill: "npm:0.3.2" @@ -12530,15 +12530,15 @@ __metadata: languageName: node linkType: hard -"open@npm:10.0.1": - version: 10.0.1 - resolution: "open@npm:10.0.1" +"open@npm:10.0.2": + version: 10.0.2 + resolution: "open@npm:10.0.2" dependencies: - default-browser: "npm:^5.2.0" + default-browser: "npm:^5.2.1" define-lazy-prop: "npm:^3.0.0" is-inside-container: "npm:^1.0.0" is-wsl: "npm:^3.1.0" - checksum: 7ce545e2e68775f06ab800c2a2ef20369bce2738e1219fd31179e1a1773f2c33fcc6b7f816a4f5e9214821cb58ae9c50f2e3f7dd8f5b02e418fbcafabf481f03 + checksum: 6f7f9e08204af00930f2998690293df1a919a61c98b225ff9e3aa09a765254b8a98bec101644ffe991452c6aabea0c6f9e49670b559d48a44bfc5238f6b58351 languageName: node linkType: hard From b92d25e28af9159c82cff6ad9532bddf55f5a503 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 30 Dec 2023 21:08:13 -0500 Subject: [PATCH 015/361] Update Material Design Icons to v7.4.47 (#19192) --- package.json | 4 ++-- yarn.lock | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index be8b0f961a1c..a66ec2870b52 100644 --- a/package.json +++ b/package.json @@ -81,8 +81,8 @@ "@material/mwc-top-app-bar-fixed": "0.27.0", "@material/top-app-bar": "=14.0.0-canary.53b3cad2f.0", "@material/web": "=1.1.1", - "@mdi/js": "7.3.67", - "@mdi/svg": "7.3.67", + "@mdi/js": "7.4.47", + "@mdi/svg": "7.4.47", "@polymer/paper-input": "3.2.1", "@polymer/paper-item": "3.0.1", "@polymer/paper-listbox": "3.0.1", diff --git a/yarn.lock b/yarn.lock index 812ddda50de9..313883fac92f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3146,17 +3146,17 @@ __metadata: languageName: node linkType: hard -"@mdi/js@npm:7.3.67": - version: 7.3.67 - resolution: "@mdi/js@npm:7.3.67" - checksum: 0f54a632d4ab3213931cc348d524f0f5e6b492ea74f8f1babe00298a8e7ae07b2fec88cfaf0cf7be0f1e427026a8da23fb8bed55b22892ad3b40b482e01cfb17 +"@mdi/js@npm:7.4.47": + version: 7.4.47 + resolution: "@mdi/js@npm:7.4.47" + checksum: c1a8fc82f23030bccc0cf324b13b73a0034d06140e79f8bc7b0e4e59275624c470e5ca6524d6141ad8c4fe3ad0f314c7af99afb3e38df163eb50d3b13b9eab17 languageName: node linkType: hard -"@mdi/svg@npm:7.3.67": - version: 7.3.67 - resolution: "@mdi/svg@npm:7.3.67" - checksum: bd9593e6cc16d140b681dedacd2a164da7884186d496c89809a9389c980c295d16edf4ba8744338d28bb6e627b1801f47c4c0cbf7b8faf7084ee87cd5d7b4250 +"@mdi/svg@npm:7.4.47": + version: 7.4.47 + resolution: "@mdi/svg@npm:7.4.47" + checksum: e5a6b80bb82cc7b7c98e9a018883aee1eaa0e98edfb62192e7ec5798fa573f30b9226629361d747de6e0a81fe6657fb37e9bc2fd89c68e9b094a07e863be4fba languageName: node linkType: hard @@ -9585,8 +9585,8 @@ __metadata: "@material/mwc-top-app-bar-fixed": "npm:0.27.0" "@material/top-app-bar": "npm:=14.0.0-canary.53b3cad2f.0" "@material/web": "npm:=1.1.1" - "@mdi/js": "npm:7.3.67" - "@mdi/svg": "npm:7.3.67" + "@mdi/js": "npm:7.4.47" + "@mdi/svg": "npm:7.4.47" "@octokit/auth-oauth-device": "npm:6.0.1" "@octokit/plugin-retry": "npm:6.0.1" "@octokit/rest": "npm:20.0.2" From d25f49b694265d4b5db3f060a041e59c369ede9e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 31 Dec 2023 13:46:23 -0500 Subject: [PATCH 016/361] Update dependency chai to v5 (#19208) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 70 ++++++++++++++++++++++++---------------------------- 2 files changed, 33 insertions(+), 39 deletions(-) diff --git a/package.json b/package.json index a66ec2870b52..3288ca8cd62f 100644 --- a/package.json +++ b/package.json @@ -190,7 +190,7 @@ "@web/dev-server-rollup": "0.4.1", "babel-loader": "9.1.3", "babel-plugin-template-html-minifier": "4.1.0", - "chai": "4.3.10", + "chai": "5.0.0", "del": "7.1.0", "eslint": "8.56.0", "eslint-config-airbnb-base": "15.0.0", diff --git a/yarn.lock b/yarn.lock index 313883fac92f..d2f7e2f24c12 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5895,10 +5895,10 @@ __metadata: languageName: node linkType: hard -"assertion-error@npm:^1.1.0": - version: 1.1.0 - resolution: "assertion-error@npm:1.1.0" - checksum: fd9429d3a3d4fd61782eb3962ae76b6d08aa7383123fca0596020013b3ebd6647891a85b05ce821c47d1471ed1271f00b0545cf6a4326cf2fc91efcc3b0fbecf +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: a0789dd882211b87116e81e2648ccb7f60340b34f19877dd020b39ebb4714e475eb943e14ba3e22201c221ef6645b7bfe10297e76b6ac95b48a9898c1211ce66 languageName: node linkType: hard @@ -6434,18 +6434,16 @@ __metadata: languageName: node linkType: hard -"chai@npm:4.3.10": - version: 4.3.10 - resolution: "chai@npm:4.3.10" +"chai@npm:5.0.0": + version: 5.0.0 + resolution: "chai@npm:5.0.0" dependencies: - assertion-error: "npm:^1.1.0" - check-error: "npm:^1.0.3" - deep-eql: "npm:^4.1.3" - get-func-name: "npm:^2.0.2" - loupe: "npm:^2.3.6" - pathval: "npm:^1.1.1" - type-detect: "npm:^4.0.8" - checksum: 9e545fd60f5efee4f06f7ad62f7b1b142932b08fbb3454db69defd511e7c58771ce51843764212da1e129b2c9d1b029fbf5f98da030fe67a95a0853e8679524f + assertion-error: "npm:^2.0.1" + check-error: "npm:^2.0.0" + deep-eql: "npm:^5.0.1" + loupe: "npm:^3.0.0" + pathval: "npm:^2.0.0" + checksum: c23d1bb3912cc36d12861d7e4010bb992aabf923a8d393bc71e776218c39f5f40778ab9f398ff962dd26857edee07ce732c9ad28a678feb1b76f99384d2e4a90 languageName: node linkType: hard @@ -6495,12 +6493,10 @@ __metadata: languageName: node linkType: hard -"check-error@npm:^1.0.3": - version: 1.0.3 - resolution: "check-error@npm:1.0.3" - dependencies: - get-func-name: "npm:^2.0.2" - checksum: e2131025cf059b21080f4813e55b3c480419256914601750b0fee3bd9b2b8315b531e551ef12560419b8b6d92a3636511322752b1ce905703239e7cc451b6399 +"check-error@npm:^2.0.0": + version: 2.0.0 + resolution: "check-error@npm:2.0.0" + checksum: 120f252c2e1ad82ef82a616662805345c6c361347bfd6203f8a28c53a158811dd0ea21278f29c8136cc9df12fc7f077d1a07124569d98fb396b3072d08f2f092 languageName: node linkType: hard @@ -7184,12 +7180,10 @@ __metadata: languageName: node linkType: hard -"deep-eql@npm:^4.1.3": - version: 4.1.3 - resolution: "deep-eql@npm:4.1.3" - dependencies: - type-detect: "npm:^4.0.0" - checksum: 12ce93ae63de187e77b076d3d51bfc28b11f98910a22c18714cce112791195e86a94f97788180994614b14562a86c9763f67c69f785e4586f806b5df39bf9301 +"deep-eql@npm:^5.0.1": + version: 5.0.1 + resolution: "deep-eql@npm:5.0.1" + checksum: f8846820213462cdca23700873810c8bc01263dcc6a1e0f8694964b64f48a6dcb1f323ef7bb8678b15553f4b82420eda19092d4ae2e2709c56af7ea77bd8e6ab languageName: node linkType: hard @@ -8966,7 +8960,7 @@ __metadata: languageName: node linkType: hard -"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": +"get-func-name@npm:^2.0.1": version: 2.0.2 resolution: "get-func-name@npm:2.0.2" checksum: 3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b @@ -9634,7 +9628,7 @@ __metadata: app-datepicker: "npm:5.1.1" babel-loader: "npm:9.1.3" babel-plugin-template-html-minifier: "npm:4.1.0" - chai: "npm:4.3.10" + chai: "npm:5.0.0" chart.js: "npm:4.4.1" comlink: "npm:4.4.1" core-js: "npm:3.34.0" @@ -11533,12 +11527,12 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^2.3.6": - version: 2.3.7 - resolution: "loupe@npm:2.3.7" +"loupe@npm:^3.0.0": + version: 3.0.2 + resolution: "loupe@npm:3.0.2" dependencies: get-func-name: "npm:^2.0.1" - checksum: 635c8f0914c2ce7ecfe4e239fbaf0ce1d2c00e4246fafcc4ed000bfdb1b8f89d05db1a220054175cca631ebf3894872a26fffba0124477fcb562f78762848fb1 + checksum: 256467bf10afaca4a5dd79b32e36fcd042bc2a247232e940c62bcc07cb114c2d7a549218eb103598e7cdb8bd32c6601fe230d80e03b8d49782973d4da11c08ed languageName: node linkType: hard @@ -12960,10 +12954,10 @@ __metadata: languageName: node linkType: hard -"pathval@npm:^1.1.1": - version: 1.1.1 - resolution: "pathval@npm:1.1.1" - checksum: b50a4751068aa3a5428f5a0b480deecedc6f537666a3630a0c2ae2d5e7c0f4bf0ee77b48404441ec1220bef0c91625e6030b3d3cf5a32ab0d9764018d1d9dbb6 +"pathval@npm:^2.0.0": + version: 2.0.0 + resolution: "pathval@npm:2.0.0" + checksum: b91575bf9cdf01757afd7b5e521eb8a0b874a49bc972d08e0047cfea0cd3c019f5614521d4bc83d2855e3fcc331db6817dfd533dd8f3d90b16bc76fad2450fc1 languageName: node linkType: hard @@ -15406,7 +15400,7 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:4.0.8, type-detect@npm:^4.0.0, type-detect@npm:^4.0.8": +"type-detect@npm:4.0.8, type-detect@npm:^4.0.8": version: 4.0.8 resolution: "type-detect@npm:4.0.8" checksum: 5179e3b8ebc51fce1b13efb75fdea4595484433f9683bbc2dca6d99789dba4e602ab7922d2656f2ce8383987467f7770131d4a7f06a26287db0615d2f4c4ce7d From 6cc9a99b770c98220d08d9da7dab4008bf6d5c20 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 31 Dec 2023 13:47:55 -0500 Subject: [PATCH 017/361] Update dependency terser-webpack-plugin to v5.3.10 (#19211) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 3288ca8cd62f..3f4e61c24329 100644 --- a/package.json +++ b/package.json @@ -235,7 +235,7 @@ "source-map-url": "0.4.1", "systemjs": "6.14.2", "tar": "6.2.0", - "terser-webpack-plugin": "5.3.9", + "terser-webpack-plugin": "5.3.10", "ts-lit-plugin": "2.0.1", "typescript": "5.3.3", "vinyl-buffer": "1.0.1", diff --git a/yarn.lock b/yarn.lock index d2f7e2f24c12..510c103b2e84 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2043,7 +2043,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.9": +"@jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.9": version: 0.3.20 resolution: "@jridgewell/trace-mapping@npm:0.3.20" dependencies: @@ -9705,7 +9705,7 @@ __metadata: superstruct: "npm:1.0.3" systemjs: "npm:6.14.2" tar: "npm:6.2.0" - terser-webpack-plugin: "npm:5.3.9" + terser-webpack-plugin: "npm:5.3.10" tinykeys: "npm:2.1.0" ts-lit-plugin: "npm:2.0.1" tsparticles-engine: "npm:2.12.0" @@ -15005,15 +15005,15 @@ __metadata: languageName: node linkType: hard -"terser-webpack-plugin@npm:5.3.9, terser-webpack-plugin@npm:^5.3.7": - version: 5.3.9 - resolution: "terser-webpack-plugin@npm:5.3.9" +"terser-webpack-plugin@npm:5.3.10, terser-webpack-plugin@npm:^5.3.7": + version: 5.3.10 + resolution: "terser-webpack-plugin@npm:5.3.10" dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.17" + "@jridgewell/trace-mapping": "npm:^0.3.20" jest-worker: "npm:^27.4.5" schema-utils: "npm:^3.1.1" serialize-javascript: "npm:^6.0.1" - terser: "npm:^5.16.8" + terser: "npm:^5.26.0" peerDependencies: webpack: ^5.1.0 peerDependenciesMeta: @@ -15023,7 +15023,7 @@ __metadata: optional: true uglify-js: optional: true - checksum: 339737a407e034b7a9d4a66e31d84d81c10433e41b8eae2ca776f0e47c2048879be482a9aa08e8c27565a2a949bc68f6e07f451bf4d9aa347dd61b3d000f5353 + checksum: fb1c2436ae1b4e983be043fa0a3d355c047b16b68f102437d08c736d7960c001e7420e2f722b9d99ce0dc70ca26a68cc63c0b82bc45f5b48671142b352a9d938 languageName: node linkType: hard @@ -15040,7 +15040,7 @@ __metadata: languageName: node linkType: hard -"terser@npm:^5.0.0, terser@npm:^5.15.1, terser@npm:^5.16.8": +"terser@npm:^5.0.0, terser@npm:^5.15.1, terser@npm:^5.26.0": version: 5.26.0 resolution: "terser@npm:5.26.0" dependencies: From d0c1481f76688a4fe836330e0972b04299b251bf Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 1 Jan 2024 13:58:47 +0100 Subject: [PATCH 018/361] Bumped version to 20240101.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4617d88e3cd2..d1e5abd3d1c4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20231228.0" +version = "20240101.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From 428604d91d2885e71b9ba23e559e9c036fea9cd5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 20:15:34 -0500 Subject: [PATCH 019/361] Update babel monorepo to v7.23.7 (#19220) --- package.json | 10 ++--- yarn.lock | 123 +++++++++++++++++++++++++-------------------------- 2 files changed, 65 insertions(+), 68 deletions(-) diff --git a/package.json b/package.json index 3f4e61c24329..7b3ad9c6a114 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "license": "Apache-2.0", "type": "module", "dependencies": { - "@babel/runtime": "7.23.6", + "@babel/runtime": "7.23.7", "@braintree/sanitize-url": "7.0.0", "@codemirror/autocomplete": "6.11.1", "@codemirror/commands": "6.3.2", @@ -150,11 +150,11 @@ "xss": "1.0.14" }, "devDependencies": { - "@babel/core": "7.23.6", + "@babel/core": "7.23.7", "@babel/helper-define-polyfill-provider": "0.4.4", - "@babel/plugin-proposal-decorators": "7.23.6", - "@babel/plugin-transform-runtime": "7.23.6", - "@babel/preset-env": "7.23.6", + "@babel/plugin-proposal-decorators": "7.23.7", + "@babel/plugin-transform-runtime": "7.23.7", + "@babel/preset-env": "7.23.7", "@babel/preset-typescript": "7.23.3", "@bundle-stats/plugin-webpack-filter": "4.8.3", "@koa/cors": "5.0.0", diff --git a/yarn.lock b/yarn.lock index 510c103b2e84..dd2a90537271 100644 --- a/yarn.lock +++ b/yarn.lock @@ -62,26 +62,26 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:7.23.6, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3": - version: 7.23.6 - resolution: "@babel/core@npm:7.23.6" +"@babel/core@npm:7.23.7, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3": + version: 7.23.7 + resolution: "@babel/core@npm:7.23.7" dependencies: "@ampproject/remapping": "npm:^2.2.0" "@babel/code-frame": "npm:^7.23.5" "@babel/generator": "npm:^7.23.6" "@babel/helper-compilation-targets": "npm:^7.23.6" "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.23.6" + "@babel/helpers": "npm:^7.23.7" "@babel/parser": "npm:^7.23.6" "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.6" + "@babel/traverse": "npm:^7.23.7" "@babel/types": "npm:^7.23.6" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: a72ba71d2f557d09ff58a5f0846344b9cea9dfcbd7418729a3a74d5b0f37a5ca024942fef4d19f248de751928a1be3d5cb0488746dd8896009dd55b974bb552e + checksum: 956841695ea801c8b4196d01072e6c1062335960715a6fcfd4009831003b526b00627c78b373ed49b1658c3622c71142f7ff04235fe839cac4a1a25ed51b90aa languageName: node linkType: hard @@ -128,9 +128,9 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/helper-create-class-features-plugin@npm:7.23.6" +"@babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.23.6, @babel/helper-create-class-features-plugin@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/helper-create-class-features-plugin@npm:7.23.7" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" "@babel/helper-environment-visitor": "npm:^7.22.20" @@ -143,7 +143,7 @@ __metadata: semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: 5e0cff67a6809d2285215057be45de9dd8900b91e3526fad5eac79023c1d6bee32aed1a04fcdf0e4d99ee4bd49ea5459cb98260c13222edf3bb983621bb452f4 + checksum: c8b3ef58fca399a25f00d703b0fb2ac1d86642d9e3bd7af04df77857641ed08aaca042ffb271ef93771f9272481fd1cf102a9bddfcee407fb126c927deeef6a7 languageName: node linkType: hard @@ -335,14 +335,14 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/helpers@npm:7.23.6" +"@babel/helpers@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/helpers@npm:7.23.7" dependencies: "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.6" + "@babel/traverse": "npm:^7.23.7" "@babel/types": "npm:^7.23.6" - checksum: 2a85fd2bcbc15a6c94dbe7b9e94d8920f9de76d164179d6895fee89c4339079d9e3e56f572bf19b5e7d1e6f1997d7fbaeaa686b47d35136852631dfd09e85c2f + checksum: ec07061dc871d406ed82c8757c4d7a510aaf15145799fb0a2c3bd3c72ca101fe82a02dd5f83ca604fbbba5de5408dd731bb1452150562bed4f3b0a2846f81f61 languageName: node linkType: hard @@ -390,31 +390,28 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.23.3" +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.23.7" dependencies: "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0 - checksum: 6e13f14949eb943d33cf4d3775a7195fa93c92851dfb648931038e9eb92a9b1709fdaa5a0ff6cf063cfcd68b3e52d280f3ebc0f3085b3e006e64dd6196ecb72a + checksum: 3b0c9554cd0048e6e7341d7b92f29d400dbc6a5a4fc2f86dbed881d32e02ece9b55bc520387bae2eac22a5ab38a0b205c29b52b181294d99b4dd75e27309b548 languageName: node linkType: hard -"@babel/plugin-proposal-decorators@npm:7.23.6": - version: 7.23.6 - resolution: "@babel/plugin-proposal-decorators@npm:7.23.6" +"@babel/plugin-proposal-decorators@npm:7.23.7": + version: 7.23.7 + resolution: "@babel/plugin-proposal-decorators@npm:7.23.7" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.23.6" + "@babel/helper-create-class-features-plugin": "npm:^7.23.7" "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.22.20" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" "@babel/plugin-syntax-decorators": "npm:^7.23.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 091796967ad728c7a00ae60c978d20f17cea08fa37bf977568880324b2619f8ce11b4a3797ef1b3137085fcb890639c49462f6be19f7cc3707e17e057df11c75 + checksum: 1fc506b113fa204323537b3299686641c29b7626f05aa098c68a818da65ce657d2398c49aea69af91c45bbdfca6086424e28d283729dba401eb93c8a16826c95 languageName: node linkType: hard @@ -670,9 +667,9 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.4" +"@babel/plugin-transform-async-generator-functions@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.7" dependencies: "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-plugin-utils": "npm:^7.22.5" @@ -680,7 +677,7 @@ __metadata: "@babel/plugin-syntax-async-generators": "npm:^7.8.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e2fc132c9033711d55209f4781e1fc73f0f4da5e0ca80a2da73dec805166b73c92a6e83571a8994cd2c893a28302e24107e90856202b24781bab734f800102bb + checksum: b1f66b23423933c27336b1161ac92efef46683321caea97e2255a666f992979376f47a5559f64188d3831fa66a4b24c2a7a40838cc0e9737e90eebe20e8e6372 languageName: node linkType: hard @@ -1137,19 +1134,19 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-runtime@npm:7.23.6": - version: 7.23.6 - resolution: "@babel/plugin-transform-runtime@npm:7.23.6" +"@babel/plugin-transform-runtime@npm:7.23.7": + version: 7.23.7 + resolution: "@babel/plugin-transform-runtime@npm:7.23.7" dependencies: "@babel/helper-module-imports": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" - babel-plugin-polyfill-corejs2: "npm:^0.4.6" - babel-plugin-polyfill-corejs3: "npm:^0.8.5" - babel-plugin-polyfill-regenerator: "npm:^0.5.3" + babel-plugin-polyfill-corejs2: "npm:^0.4.7" + babel-plugin-polyfill-corejs3: "npm:^0.8.7" + babel-plugin-polyfill-regenerator: "npm:^0.5.4" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 54e540ec04f05f664c69db36a78b5db56b0d3e25bbe34d7f11cfe21cc5aad5240661f5ada630c7b2abcae99d229851aafbb6b2218cf285771379e0844a3f24a9 + checksum: 1e0b21c943e565e6a2a859991059f5b5a8b917689aab9b3beb172babece1843b42f9ae9ff9913f01134fb201fd67ac2831559578949c7287e7c782e6d6740de8 languageName: node linkType: hard @@ -1270,9 +1267,9 @@ __metadata: languageName: node linkType: hard -"@babel/preset-env@npm:7.23.6, @babel/preset-env@npm:^7.11.0": - version: 7.23.6 - resolution: "@babel/preset-env@npm:7.23.6" +"@babel/preset-env@npm:7.23.7, @babel/preset-env@npm:^7.11.0": + version: 7.23.7 + resolution: "@babel/preset-env@npm:7.23.7" dependencies: "@babel/compat-data": "npm:^7.23.5" "@babel/helper-compilation-targets": "npm:^7.23.6" @@ -1280,7 +1277,7 @@ __metadata: "@babel/helper-validator-option": "npm:^7.23.5" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.23.3" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.23.3" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.23.3" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.23.7" "@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators": "npm:^7.8.4" "@babel/plugin-syntax-class-properties": "npm:^7.12.13" @@ -1301,7 +1298,7 @@ __metadata: "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" "@babel/plugin-transform-arrow-functions": "npm:^7.23.3" - "@babel/plugin-transform-async-generator-functions": "npm:^7.23.4" + "@babel/plugin-transform-async-generator-functions": "npm:^7.23.7" "@babel/plugin-transform-async-to-generator": "npm:^7.23.3" "@babel/plugin-transform-block-scoped-functions": "npm:^7.23.3" "@babel/plugin-transform-block-scoping": "npm:^7.23.4" @@ -1349,14 +1346,14 @@ __metadata: "@babel/plugin-transform-unicode-regex": "npm:^7.23.3" "@babel/plugin-transform-unicode-sets-regex": "npm:^7.23.3" "@babel/preset-modules": "npm:0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2: "npm:^0.4.6" - babel-plugin-polyfill-corejs3: "npm:^0.8.5" - babel-plugin-polyfill-regenerator: "npm:^0.5.3" + babel-plugin-polyfill-corejs2: "npm:^0.4.7" + babel-plugin-polyfill-corejs3: "npm:^0.8.7" + babel-plugin-polyfill-regenerator: "npm:^0.5.4" core-js-compat: "npm:^3.31.0" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b47e9e7cdb0d31b2a6919ffb1b767f8159a69b000e257c1dad1121dea8c42d7ec12a892a691d1a8e90cde86edd41b017254574ec6b82a984013bb3c9e3df2b36 + checksum: 2059dee350c39aba0a1f128d00ccfd7abf97f92a9b661f4db07a96c11d91c928a9f1df39477583f068090627bff571b4415f1a4f94008d29f6ad8b124e69804e languageName: node linkType: hard @@ -1395,12 +1392,12 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:7.23.6, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4": - version: 7.23.6 - resolution: "@babel/runtime@npm:7.23.6" +"@babel/runtime@npm:7.23.7, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4": + version: 7.23.7 + resolution: "@babel/runtime@npm:7.23.7" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: 4c4ab16f0361c59fb23956e4d0a29935f1f8a64aa8dd37876ce38355b6f4d8f0e54237aacb89c73b1532def60539ddde2d651523c8fa887b30b19a8cf0c465b0 + checksum: b29cf3ca6277aea8c5c823d9b86e7f7153757f07eaaa81d726f125de00ac0e7451c90845770f919826a94ade8f71a6bda9c0421410dfcc285ee17a40f8f8ca00 languageName: node linkType: hard @@ -1415,9 +1412,9 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/traverse@npm:7.23.6" +"@babel/traverse@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/traverse@npm:7.23.7" dependencies: "@babel/code-frame": "npm:^7.23.5" "@babel/generator": "npm:^7.23.6" @@ -1429,7 +1426,7 @@ __metadata: "@babel/types": "npm:^7.23.6" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: ee4434a3ce792ee8956b64d76843caa1dda4779bb621ed9f951dd3551965bf1f292f097011c9730ecbc0b57f02434b1fa5a771610a2ef570726b0df0fc3332d9 + checksum: 3215e59429963c8dac85c26933372cdd322952aa9930e4bc5ef2d0e4bd7a1510d1ecf8f8fd860ace5d4d9fe496d23805a1ea019a86410aee4111de5f63ee84f9 languageName: node linkType: hard @@ -6003,7 +6000,7 @@ __metadata: languageName: node linkType: hard -"babel-plugin-polyfill-corejs2@npm:^0.4.6": +"babel-plugin-polyfill-corejs2@npm:^0.4.7": version: 0.4.7 resolution: "babel-plugin-polyfill-corejs2@npm:0.4.7" dependencies: @@ -6016,7 +6013,7 @@ __metadata: languageName: node linkType: hard -"babel-plugin-polyfill-corejs3@npm:^0.8.5": +"babel-plugin-polyfill-corejs3@npm:^0.8.7": version: 0.8.7 resolution: "babel-plugin-polyfill-corejs3@npm:0.8.7" dependencies: @@ -6028,7 +6025,7 @@ __metadata: languageName: node linkType: hard -"babel-plugin-polyfill-regenerator@npm:^0.5.3": +"babel-plugin-polyfill-regenerator@npm:^0.5.4": version: 0.5.4 resolution: "babel-plugin-polyfill-regenerator@npm:0.5.4" dependencies: @@ -9514,13 +9511,13 @@ __metadata: version: 0.0.0-use.local resolution: "home-assistant-frontend@workspace:." dependencies: - "@babel/core": "npm:7.23.6" + "@babel/core": "npm:7.23.7" "@babel/helper-define-polyfill-provider": "npm:0.4.4" - "@babel/plugin-proposal-decorators": "npm:7.23.6" - "@babel/plugin-transform-runtime": "npm:7.23.6" - "@babel/preset-env": "npm:7.23.6" + "@babel/plugin-proposal-decorators": "npm:7.23.7" + "@babel/plugin-transform-runtime": "npm:7.23.7" + "@babel/preset-env": "npm:7.23.7" "@babel/preset-typescript": "npm:7.23.3" - "@babel/runtime": "npm:7.23.6" + "@babel/runtime": "npm:7.23.7" "@braintree/sanitize-url": "npm:7.0.0" "@bundle-stats/plugin-webpack-filter": "npm:4.8.3" "@codemirror/autocomplete": "npm:6.11.1" From c650e23432d9f0d1a875c258f5cffc5d6f0bed55 Mon Sep 17 00:00:00 2001 From: JLo Date: Tue, 2 Jan 2024 12:08:05 +0100 Subject: [PATCH 020/361] Review on automation editor text (#19223) - Added `.` to bloc descriptions - Changed "Other" into "OTher triggers" "Other conditions" and "Other actions" - Adapted a few descriptions --- src/translations/en.json | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/translations/en.json b/src/translations/en.json index 0039d9926f56..0ea3cf853f2e 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2492,13 +2492,13 @@ "groups": { "entity": { "label": "Entity", - "description": "When something happens to an entity" + "description": "When something happens to an entity." }, "time_location": { "label": "Time and location", "description": "When someone enters or leaves a zone, or at a specific time." }, - "other": { "label": "Other" } + "other": { "label": "Other triggers" } }, "type": { "calendar": { @@ -2534,7 +2534,7 @@ "context_user_picked": "User firing event", "context_user_pick": "Select user", "description": { - "picker": "When an event is being received (event is an advanced concept in Home Assistant)", + "picker": "When an event is being received (event is an advanced concept in Home Assistant).", "full": "When {eventTypes} event is fired" } }, @@ -2546,7 +2546,7 @@ "enter": "Enter", "leave": "Leave", "description": { - "picker": "When an entity created by a geolocation platform appears in or disappears from a zone", + "picker": "When an entity created by a geolocation platform appears in or disappears from a zone.", "full": "When {source} {event, select, \n enter {enters}\n leave {leaves} other {} \n} {zone} {numberOfZones, plural,\n one {zone}\n other {zones}\n}" } }, @@ -2608,7 +2608,7 @@ "updated": "updated" }, "description": { - "picker": "When a persistent notification is added or removed", + "picker": "When a persistent notification is added or removed.", "full": "When a persistent notification is updated" } }, @@ -2619,7 +2619,7 @@ "sunset": "Sunset", "offset": "Offset (optional)", "description": { - "picker": "When the sun sets or rises", + "picker": "When the sun sets or rises.", "sets": "When the sun sets{hasDuration, select, \n true { offset by {duration}} \n other {}\n }", "rises": "When the sun rises{hasDuration, select, \n true { offset by {duration}} \n other {}\n }" } @@ -2648,7 +2648,7 @@ "value_template": "Value template", "for": "For", "description": { - "picker": "When a template is evaluated to true.", + "picker": "When a template evaluates to true.", "full": "When a template changes from false to true{hasDuration, select, \n true { for {duration}} \n other {}\n }" } }, @@ -2669,7 +2669,7 @@ "minutes": "Minutes", "seconds": "Seconds", "description": { - "picker": "Periodically, every defined interval of time." + "picker": "Periodically, at a defined interval." } }, "webhook": { @@ -2692,7 +2692,7 @@ "enter": "Enter", "leave": "Leave", "description": { - "picker": "When someone (or something) enters or leaves a zone", + "picker": "When someone (or something) enters or leaves a zone.", "full": "When {entity} {event, select, \n enter {enters}\n leave {leaves} other {} \n} {zone} {numberOfZones, plural,\n one {zone} \n other {zones}\n}" } } @@ -2734,7 +2734,7 @@ "label": "Time and location", "description": "If someone is in a zone or if the current time is before or after a specified time." }, - "other": { "label": "Other" }, + "other": { "label": "Other conditions" }, "building_blocks": { "label": "Building blocks", "description": "Build more complex conditions." @@ -2766,7 +2766,7 @@ "not": { "label": "Not", "description": { - "picker": "Test if a condition is not true", + "picker": "Test if a condition is not true.", "no_conditions": "Test if no condition matches", "one_condition": "Test if 1 condition does not match", "full": "Test if none of {count} conditions match" @@ -2800,7 +2800,7 @@ "label": "[%key:ui::panel::config::automation::editor::triggers::type::state::label%]", "state": "[%key:ui::panel::config::automation::editor::triggers::type::state::label%]", "description": { - "picker": "If an entity (or attribute) is in a specific state", + "picker": "If an entity (or attribute) is in a specific state.", "no_entity": "Confirm state", "full": "Confirm{hasAttribute, select, \n true { {attribute} of}\n other {}\n} {numberOfEntities, plural,\n zero {an entity is}\n one {{entities} is}\n other {{entities} are}\n} {numberOfStates, plural,\n zero {a state}\n other {{states}}\n}{hasDuration, select, \n true { for {duration}} \n other {}\n }" } @@ -2821,7 +2821,7 @@ "label": "[%key:ui::panel::config::automation::editor::triggers::type::template::label%]", "value_template": "[%key:ui::panel::config::automation::editor::triggers::type::template::value_template%]", "description": { - "picker": "If a template is evaluated to true.", + "picker": "If a template evaluates to true.", "full": "Test if template renders a value equal to true" } }, @@ -2844,7 +2844,7 @@ "sun": "Sunday" }, "description": { - "picker": "If the current time is before or after a specified time", + "picker": "If the current time is before or after a specified time.", "full": "Confirm the {hasTime, select, \n after {time is after {time_after}}\n before {time is before {time_before}}\n after_before {time is after {time_after} and before {time_before}} \n other {}\n }{hasTimeAndDay, select, \n true { and the }\n other {}\n}{hasDay, select, \n true { day is {day}}\n other {}\n}" } }, @@ -2862,7 +2862,7 @@ "entity": "[%key:ui::panel::config::automation::editor::triggers::type::zone::entity%]", "zone": "[%key:ui::panel::config::automation::editor::triggers::type::zone::label%]", "description": { - "picker": "If someone (or something) is in a zone", + "picker": "If someone (or something) is in a zone.", "full": "Confirm {entity} {numberOfEntities, plural,\n one {is}\n other {are}\n} in {zone} {numberOfZones, plural,\n one {zone} \n other {zones}\n} " } } @@ -2899,7 +2899,7 @@ "continue_on_error": "Continue on error", "groups": { "helpers": { "label": "Helpers" }, - "other": { "label": "Other" }, + "other": { "label": "Other actions" }, "building_blocks": { "label": "Building blocks", "description": "Build more complex sequences of actions." @@ -3069,14 +3069,14 @@ "response_variable": "The name of the variable to use as response", "error": "Stop because of an unexpected error", "description": { - "picker": "Stop the sequence of actions", + "picker": "Stop the sequence of actions.", "full": "Stop {hasReason, select, \n true { because: {reason}} \n other {}\n }" } }, "parallel": { "label": "Run in parallel", "description": { - "picker": "perform a sequence of actions in parallel.", + "picker": "Perform a sequence of actions in parallel.", "full": "Run {number} {number, plural,\n one {action}\n other {actions}\n} in parallel" } }, From 52fcf64cfdb86e3958af9beca9e069a0a734f8eb Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 13:36:06 +0100 Subject: [PATCH 021/361] Automation editor tweaks (#19225) * Automation editor tweaks * fix styling --- src/data/condition.ts | 1 - .../add-automation-element-dialog.ts | 145 +++++++++++++----- .../condition/ha-automation-condition.ts | 1 + .../types/ha-automation-condition-device.ts | 1 + .../show-add-automation-element-dialog.ts | 1 + .../types/ha-automation-trigger-device.ts | 1 + 6 files changed, 108 insertions(+), 42 deletions(-) diff --git a/src/data/condition.ts b/src/data/condition.ts index 44a0e218609c..d8c7af44fecc 100644 --- a/src/data/condition.ts +++ b/src/data/condition.ts @@ -46,7 +46,6 @@ export const CONDITION_GROUPS: AutomationElementGroup = { icon: mdiDotsHorizontal, members: { template: {}, - trigger: {}, }, }, } as const; diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index b96283a61dd8..31760dca1bc1 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -1,7 +1,14 @@ import "@material/mwc-list/mwc-list"; import { mdiClose, mdiContentPaste, mdiPlus } from "@mdi/js"; import Fuse, { IFuseOptions } from "fuse.js"; -import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; +import { + CSSResultGroup, + LitElement, + PropertyValues, + css, + html, + nothing, +} from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { ifDefined } from "lit/directives/if-defined"; import { repeat } from "lit/directives/repeat"; @@ -42,6 +49,8 @@ import { AddAutomationElementDialogParams, PASTE_VALUE, } from "./show-add-automation-element-dialog"; +import { computeDomain } from "../../../common/entity/compute_domain"; +import { deepEqual } from "../../../common/util/deep-equal"; const TYPES = { trigger: { groups: TRIGGER_GROUPS, icons: TRIGGER_ICONS }, @@ -93,13 +102,15 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { @state() private _manifests?: DomainManifestLookup; + @state() private _domains?: Set; + @query("ha-dialog") private _dialog?: HaDialog; private _fullScreen = false; - private _width?: number; + @state() private _width?: number; - private _height?: number; + @state() private _height?: number; public showDialog(params): void { this._params = params; @@ -124,6 +135,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { this._prev = undefined; this._filter = ""; this._manifests = undefined; + this._domains = undefined; } private _convertToItem = ( @@ -152,6 +164,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { private _getFilteredItems = memoizeOne( ( type: AddAutomationElementDialogParams["type"], + root: AddAutomationElementDialogParams["root"], group: string | undefined, filter: string, localize: LocalizeFunc, @@ -164,6 +177,10 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { : TYPES[type].groups[group].members! : TYPES[type].groups; + if (type === "condition" && group === "other" && !root) { + groups.trigger = {}; + } + const flattenGroups = (grp: AutomationElementGroup) => Object.entries(grp).map(([key, options]) => options.members @@ -191,7 +208,9 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { private _getGroupItems = memoizeOne( ( type: AddAutomationElementDialogParams["type"], + root: AddAutomationElementDialogParams["root"], group: string | undefined, + domains: Set | undefined, localize: LocalizeFunc, services: HomeAssistant["services"], manifests?: DomainManifestLookup @@ -208,6 +227,10 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { ? TYPES[type].groups[group].members! : TYPES[type].groups; + if (type === "condition" && group === "other" && !root) { + groups.trigger = {}; + } + const result = Object.entries(groups).map(([key, options]) => this._convertToItem(key, options, type, localize) ); @@ -215,15 +238,33 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { if (type === "action") { if (!this._group) { result.unshift( - ...this._serviceGroups(localize, services, manifests, undefined) + ...this._serviceGroups( + localize, + services, + manifests, + domains, + undefined + ) ); } else if (this._group === "helpers") { result.unshift( - ...this._serviceGroups(localize, services, manifests, "helper") + ...this._serviceGroups( + localize, + services, + manifests, + domains, + "helper" + ) ); } else if (this._group === "other") { result.unshift( - ...this._serviceGroups(localize, services, manifests, "other") + ...this._serviceGroups( + localize, + services, + manifests, + domains, + "other" + ) ); } } @@ -243,42 +284,44 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { } ); - private _serviceGroups = memoizeOne( - ( - localize: LocalizeFunc, - services: HomeAssistant["services"], - manifests: DomainManifestLookup | undefined, - type: "helper" | "other" | undefined - ): ListItem[] => { - if (!services || !manifests) { - return []; - } - const result: ListItem[] = []; - Object.keys(services).forEach((domain) => { - const manifest = manifests[domain]; - if ( - (type === undefined && - manifest?.integration_type === "entity" && - !ENTITY_DOMAINS_OTHER.has(domain)) || - (type === "helper" && manifest?.integration_type === "helper") || - (type === "other" && - (ENTITY_DOMAINS_OTHER.has(domain) || - !["helper", "entity"].includes(manifest?.integration_type || ""))) - ) { - result.push({ - group: true, - icon: domainIcon(domain), - key: `${SERVICE_PREFIX}${domain}`, - name: domainToName(localize, domain, manifest), - description: "", - }); - } - }); - return result.sort((a, b) => - stringCompare(a.name, b.name, this.hass.locale.language) - ); + private _serviceGroups = ( + localize: LocalizeFunc, + services: HomeAssistant["services"], + manifests: DomainManifestLookup | undefined, + domains: Set | undefined, + type: "helper" | "other" | undefined + ): ListItem[] => { + if (!services || !manifests) { + return []; } - ); + const result: ListItem[] = []; + Object.keys(services).forEach((domain) => { + const manifest = manifests[domain]; + const domainUsed = !domains ? true : domains.has(domain); + if ( + (type === undefined && + manifest?.integration_type === "entity" && + domainUsed && + !ENTITY_DOMAINS_OTHER.has(domain)) || + (type === "helper" && manifest?.integration_type === "helper") || + (type === "other" && + (ENTITY_DOMAINS_OTHER.has(domain) || + (!domainUsed && manifest?.integration_type === "entity") || + !["helper", "entity"].includes(manifest?.integration_type || ""))) + ) { + result.push({ + group: true, + icon: domainIcon(domain), + key: `${SERVICE_PREFIX}${domain}`, + name: domainToName(localize, domain, manifest), + description: "", + }); + } + }); + return result.sort((a, b) => + stringCompare(a.name, b.name, this.hass.locale.language) + ); + }; private _services = memoizeOne( ( @@ -368,6 +411,19 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { this._height = boundingRect?.height; } + protected willUpdate(changedProperties: PropertyValues): void { + if ( + this._params?.type === "action" && + changedProperties.has("hass") && + changedProperties.get("hass")?.states !== this.hass.states + ) { + const domains = new Set(Object.keys(this.hass.states).map(computeDomain)); + if (!deepEqual(domains, this._domains)) { + this._domains = domains; + } + } + } + protected render() { if (!this._params) { return nothing; @@ -376,6 +432,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { const items = this._filter ? this._getFilteredItems( this._params.type, + this._params.root, this._group, this._filter, this.hass.localize, @@ -384,7 +441,9 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { ) : this._getGroupItems( this._params.type, + this._params.root, this._group, + this._domains, this.hass.localize, this.hass.services, this._manifests @@ -562,6 +621,10 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { ha-icon-next { width: 24px; } + mwc-list { + max-height: 468px; + max-width: 100vw; + } search-input { display: block; margin: 0 16px; diff --git a/src/panels/config/automation/condition/ha-automation-condition.ts b/src/panels/config/automation/condition/ha-automation-condition.ts index 27364b92a3ed..ecf4f8823770 100644 --- a/src/panels/config/automation/condition/ha-automation-condition.ts +++ b/src/panels/config/automation/condition/ha-automation-condition.ts @@ -203,6 +203,7 @@ export default class HaAutomationCondition extends LitElement { showAddAutomationElementDialog(this, { type: "condition", add: this._addCondition, + root: !this.nested, clipboardItem: this._clipboard?.condition?.condition, }); } diff --git a/src/panels/config/automation/condition/types/ha-automation-condition-device.ts b/src/panels/config/automation/condition/types/ha-automation-condition-device.ts index 71568fe02c10..4593a5f70123 100644 --- a/src/panels/config/automation/condition/types/ha-automation-condition-device.ts +++ b/src/panels/config/automation/condition/types/ha-automation-condition-device.ts @@ -168,6 +168,7 @@ export class HaDeviceCondition extends LitElement { } ha-form { + display: block; margin-top: 24px; } `; diff --git a/src/panels/config/automation/show-add-automation-element-dialog.ts b/src/panels/config/automation/show-add-automation-element-dialog.ts index c497ca85c620..55453505121d 100644 --- a/src/panels/config/automation/show-add-automation-element-dialog.ts +++ b/src/panels/config/automation/show-add-automation-element-dialog.ts @@ -6,6 +6,7 @@ export interface AddAutomationElementDialogParams { type: "trigger" | "condition" | "action"; add: (key: string) => void; clipboardItem: string | undefined; + root?: boolean; group?: string; } const loadDialog = () => import("./add-automation-element-dialog"); diff --git a/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts b/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts index 8b3a63575220..1b94ff6138b2 100644 --- a/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts +++ b/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts @@ -174,6 +174,7 @@ export class HaDeviceTrigger extends LitElement { } ha-form { + display: block; margin-top: 24px; } `; From 1b6def487550eeb6b97e4edcd6fcf901ed306e6c Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Tue, 2 Jan 2024 05:07:34 -0800 Subject: [PATCH 022/361] Localize a device action string (#19203) --- src/data/script_i18n.ts | 4 +++- src/translations/en.json | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/data/script_i18n.ts b/src/data/script_i18n.ts index 1ba30198bd3e..4b07b84f0ed5 100644 --- a/src/data/script_i18n.ts +++ b/src/data/script_i18n.ts @@ -404,7 +404,9 @@ const tryDescribeAction = ( if (actionType === "device_action") { const config = action as DeviceAction; if (!config.device_id) { - return "Device action"; + return hass.localize( + `${actionTranslationBaseKey}.device_id.description.no_device` + ); } const localized = localizeDeviceAutomationAction( hass, diff --git a/src/translations/en.json b/src/translations/en.json index 0ea3cf853f2e..c176cf65c96a 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2990,7 +2990,8 @@ "flash": "Flash" }, "description": { - "picker": "Do something on a device. Great way to start." + "picker": "Do something on a device. Great way to start.", + "no_device": "Device action" } }, "activate_scene": { From 5ac03604949cf8bf3ab616d9d22ff472f428ede4 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 16:08:26 +0100 Subject: [PATCH 023/361] Remove references to "service call" from actions (#19226) --- src/components/ha-service-control.ts | 28 ++++++++++++++----- src/data/script.ts | 2 ++ src/data/script_i18n.ts | 5 +++- .../action/ha-automation-action-row.ts | 10 ++++++- .../automation/action/ha-automation-action.ts | 1 + src/translations/en.json | 1 + 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/components/ha-service-control.ts b/src/components/ha-service-control.ts index f1ae8ee54bac..119418355c64 100644 --- a/src/components/ha-service-control.ts +++ b/src/components/ha-service-control.ts @@ -4,7 +4,14 @@ import { HassServices, HassServiceTarget, } from "home-assistant-js-websocket"; -import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit"; +import { + css, + CSSResultGroup, + html, + LitElement, + PropertyValues, + nothing, +} from "lit"; import { customElement, property, query, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { ensureArray } from "../common/array/ensure-array"; @@ -83,6 +90,8 @@ export class HaServiceControl extends LitElement { @property({ type: Boolean }) public showAdvanced?: boolean; + @property({ type: Boolean, reflect: true }) public hidePicker?: boolean; + @state() private _value!: this["value"]; @state() private _checkedKeys = new Set(); @@ -363,12 +372,14 @@ export class HaServiceControl extends LitElement { )) || serviceData?.description; - return html` + return html`${this.hidePicker + ? nothing + : html``}
${description ? html`

${description}

` : ""} ${this._manifest @@ -735,6 +746,9 @@ export class HaServiceControl extends LitElement { margin: var(--service-control-padding, 0 16px); padding: 16px 0; } + :host([hidePicker]) p { + padding-top: 0; + } .checkbox-spacer { width: 32px; } diff --git a/src/data/script.ts b/src/data/script.ts index f0b5e7151b51..08910dc88fcb 100644 --- a/src/data/script.ts +++ b/src/data/script.ts @@ -52,6 +52,7 @@ export const serviceActionStruct: Describe = assign( target: optional(targetStruct), data: optional(object()), response_variable: optional(string()), + metadata: optional(object()), }) ); @@ -133,6 +134,7 @@ export interface ServiceAction extends BaseAction { target?: HassServiceTarget; data?: Record; response_variable?: string; + metadata?: Record; } export interface DeviceAction extends BaseAction { diff --git a/src/data/script_i18n.ts b/src/data/script_i18n.ts index 4b07b84f0ed5..3d7d8c5a1da4 100644 --- a/src/data/script_i18n.ts +++ b/src/data/script_i18n.ts @@ -168,8 +168,11 @@ const tryDescribeAction = ( const service = hass.localize(`component.${domain}.services.${serviceName}.name`) || hass.services[domain][serviceName]?.name; + return hass.localize( - `${actionTranslationBaseKey}.service.description.service_based_on_name`, + `${actionTranslationBaseKey}.service.description.${ + config.metadata ? "service_name" : "service_based_on_name" + }`, { name: service ? `${domainToName(hass.localize, domain)}: ${service}` diff --git a/src/panels/config/automation/action/ha-automation-action-row.ts b/src/panels/config/automation/action/ha-automation-action-row.ts index f09c901c8e1a..0e58c0e8b2b5 100644 --- a/src/panels/config/automation/action/ha-automation-action-row.ts +++ b/src/panels/config/automation/action/ha-automation-action-row.ts @@ -29,6 +29,8 @@ import { classMap } from "lit/directives/class-map"; import { storage } from "../../../../common/decorators/storage"; import { dynamicElement } from "../../../../common/dom/dynamic-element-directive"; import { fireEvent } from "../../../../common/dom/fire_event"; +import { computeDomain } from "../../../../common/entity/compute_domain"; +import { domainIconWithoutDefault } from "../../../../common/entity/domain_icon"; import { capitalizeFirstLetter } from "../../../../common/string/capitalize-first-letter"; import { handleStructError } from "../../../../common/structs/handle-errors"; import "../../../../components/ha-alert"; @@ -190,7 +192,13 @@ export default class HaAutomationActionRow extends LitElement {

${capitalizeFirstLetter( describeAction(this.hass, this._entityReg, this.action) diff --git a/src/panels/config/automation/action/ha-automation-action.ts b/src/panels/config/automation/action/ha-automation-action.ts index dca4bab6acde..ce312a7bd399 100644 --- a/src/panels/config/automation/action/ha-automation-action.ts +++ b/src/panels/config/automation/action/ha-automation-action.ts @@ -191,6 +191,7 @@ export default class HaAutomationAction extends LitElement { } else if (isService(action)) { actions = this.actions.concat({ service: getService(action), + metadata: {}, }); } else { const elClass = customElements.get( diff --git a/src/translations/en.json b/src/translations/en.json index c176cf65c96a..e771c8fe1910 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2914,6 +2914,7 @@ "description": { "service_based_on_template": "Call a service based on a template on {targets}", "service_based_on_name": "Call a service ''{name}'' on {targets}", + "service_name": "''{name}'' on {targets}", "service": "Call a service", "target_template": "templated {name}", "target_unknown_entity": "unknown entity", From 6f7da16d1d367a354073d5b3d804cfb6103b36e9 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 18:11:34 +0100 Subject: [PATCH 024/361] Use brand icons in actions (#19227) --- src/common/const.ts | 4 ++ .../add-automation-element-dialog.ts | 39 ++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/common/const.ts b/src/common/const.ts index 66c14e64e140..68f4fa97b1c1 100644 --- a/src/common/const.ts +++ b/src/common/const.ts @@ -29,6 +29,7 @@ import { mdiFlash, mdiFlower, mdiFormatListBulleted, + mdiFormatListCheckbox, mdiFormTextbox, mdiGauge, mdiGoogleAssistant, @@ -64,6 +65,7 @@ import { mdiTransmissionTower, mdiWater, mdiWaterPercent, + mdiWeatherPartlyCloudy, mdiWeatherPouring, mdiWeatherRainy, mdiWeatherWindy, @@ -128,6 +130,7 @@ export const FIXED_DOMAIN_ICONS = { updater: mdiCloudUpload, vacuum: mdiRobotVacuum, wake_word: mdiChatSleep, + weather: mdiWeatherPartlyCloudy, zone: mdiMapMarkerRadius, }; @@ -166,6 +169,7 @@ export const FIXED_DEVICE_CLASS_ICONS = { precipitation_intensity: mdiWeatherPouring, pressure: mdiGauge, reactive_power: mdiFlash, + shopping_List: mdiFormatListCheckbox, signal_strength: mdiWifi, sound_pressure: mdiEarHearing, speed: mdiSpeedometer, diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index 31760dca1bc1..0e930b7c9916 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -15,7 +15,7 @@ import { repeat } from "lit/directives/repeat"; import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../common/dom/fire_event"; -import { domainIcon } from "../../../common/entity/domain_icon"; +import { domainIconWithoutDefault } from "../../../common/entity/domain_icon"; import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event"; import { stringCompare } from "../../../common/string/compare"; import { LocalizeFunc } from "../../../common/translations/localize"; @@ -45,6 +45,7 @@ import { TRIGGER_GROUPS, TRIGGER_ICONS } from "../../../data/trigger"; import { HassDialog } from "../../../dialogs/make-dialog-manager"; import { haStyle, haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; +import { brandsUrl } from "../../../util/brands-url"; import { AddAutomationElementDialogParams, PASTE_VALUE, @@ -68,7 +69,8 @@ interface ListItem { key: string; name: string; description: string; - icon: string; + icon?: string; + image?: string; group: boolean; } @@ -309,9 +311,17 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { (!domainUsed && manifest?.integration_type === "entity") || !["helper", "entity"].includes(manifest?.integration_type || ""))) ) { + const icon = domainIconWithoutDefault(domain); result.push({ group: true, - icon: domainIcon(domain), + icon, + image: !icon + ? brandsUrl({ + domain, + type: "icon", + darkOptimized: this.hass.themes?.darkMode, + }) + : undefined, key: `${SERVICE_PREFIX}${domain}`, name: domainToName(localize, domain, manifest), description: "", @@ -345,9 +355,17 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { const services_keys = Object.keys(services[dmn]); for (const service of services_keys) { + const icon = domainIconWithoutDefault(dmn); result.push({ group: false, - icon: domainIcon(dmn), + icon, + image: !icon + ? brandsUrl({ + domain: dmn, + type: "icon", + darkOptimized: this.hass.themes?.darkMode, + }) + : undefined, key: `${SERVICE_PREFIX}${dmn}.${service}`, name: `${domain ? "" : `${domainToName(localize, dmn)}: `}${ this.hass.localize(`component.${dmn}.services.${service}.name`) || @@ -556,7 +574,18 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { > ${item.name} ${item.description} - + ${item.icon + ? html`` + : html``} ${item.group ? html`` : html` Date: Tue, 2 Jan 2024 18:31:18 +0100 Subject: [PATCH 025/361] Change format of service description (#19229) --- src/data/script_i18n.ts | 15 ++++++++++++--- src/translations/en.json | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/data/script_i18n.ts b/src/data/script_i18n.ts index 3d7d8c5a1da4..40c823bc862f 100644 --- a/src/data/script_i18n.ts +++ b/src/data/script_i18n.ts @@ -169,10 +169,19 @@ const tryDescribeAction = ( hass.localize(`component.${domain}.services.${serviceName}.name`) || hass.services[domain][serviceName]?.name; + if (config.metadata) { + return hass.localize( + `${actionTranslationBaseKey}.service.description.service_name`, + { + domain: domainToName(hass.localize, domain), + name: service || config.service, + targets: formatListWithAnds(hass.locale, targets), + } + ); + } + return hass.localize( - `${actionTranslationBaseKey}.service.description.${ - config.metadata ? "service_name" : "service_based_on_name" - }`, + `${actionTranslationBaseKey}.service.description.service_based_on_name`, { name: service ? `${domainToName(hass.localize, domain)}: ${service}` diff --git a/src/translations/en.json b/src/translations/en.json index e771c8fe1910..6ef41c81c129 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2914,7 +2914,7 @@ "description": { "service_based_on_template": "Call a service based on a template on {targets}", "service_based_on_name": "Call a service ''{name}'' on {targets}", - "service_name": "''{name}'' on {targets}", + "service_name": "{domain} ''{name}'' on {targets}", "service": "Call a service", "target_template": "templated {name}", "target_unknown_entity": "unknown entity", From def2eadc24b58e4f4af9bf4bb29ef59614564427 Mon Sep 17 00:00:00 2001 From: Josh McCarty Date: Tue, 2 Jan 2024 10:35:08 -0700 Subject: [PATCH 026/361] Add missing device classes for entity-registry-settings-editor (#19231) * Add connectivity device class for binary sensors * Add update device class * Separate connectivity and update --- src/panels/config/entities/entity-registry-settings-editor.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/panels/config/entities/entity-registry-settings-editor.ts b/src/panels/config/entities/entity-registry-settings-editor.ts index 14d88e12afc7..9e7213e41475 100644 --- a/src/panels/config/entities/entity-registry-settings-editor.ts +++ b/src/panels/config/entities/entity-registry-settings-editor.ts @@ -118,6 +118,8 @@ const OVERRIDE_DEVICE_CLASSES = { "carbon_monoxide", "moisture", ], // Alarm + ["connectivity"], // Connectivity + ["update"], // Update ], }; From 7d6dfaad153d4f587a7dde3a734d282ea1cb3789 Mon Sep 17 00:00:00 2001 From: JLo Date: Tue, 2 Jan 2024 18:39:55 +0100 Subject: [PATCH 027/361] New copy for device trigger in automation editor (#19232) New copy for device trigger in automation editor: "Set of conditions provided by your device. Great way to start." --- src/translations/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/translations/en.json b/src/translations/en.json index 6ef41c81c129..53306cd8b77d 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2760,7 +2760,7 @@ "preset_mode": "Preset mode" }, "description": { - "picker": "If a device is in a certain state. Great way to start." + "picker": "Set of conditions provided by your device. Great way to start." } }, "not": { From 2add88ccc23d87a92329b3ee07128389ef1c0ed4 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Tue, 2 Jan 2024 05:07:34 -0800 Subject: [PATCH 028/361] Localize a device action string (#19203) --- src/data/script_i18n.ts | 4 +++- src/translations/en.json | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/data/script_i18n.ts b/src/data/script_i18n.ts index 1ba30198bd3e..4b07b84f0ed5 100644 --- a/src/data/script_i18n.ts +++ b/src/data/script_i18n.ts @@ -404,7 +404,9 @@ const tryDescribeAction = ( if (actionType === "device_action") { const config = action as DeviceAction; if (!config.device_id) { - return "Device action"; + return hass.localize( + `${actionTranslationBaseKey}.device_id.description.no_device` + ); } const localized = localizeDeviceAutomationAction( hass, diff --git a/src/translations/en.json b/src/translations/en.json index 0039d9926f56..a3070c0787b1 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2990,7 +2990,8 @@ "flash": "Flash" }, "description": { - "picker": "Do something on a device. Great way to start." + "picker": "Do something on a device. Great way to start.", + "no_device": "Device action" } }, "activate_scene": { From 4fcf99faa7b6735aee1550b785a76df8e633dcca Mon Sep 17 00:00:00 2001 From: JLo Date: Tue, 2 Jan 2024 12:08:05 +0100 Subject: [PATCH 029/361] Review on automation editor text (#19223) - Added `.` to bloc descriptions - Changed "Other" into "OTher triggers" "Other conditions" and "Other actions" - Adapted a few descriptions --- src/translations/en.json | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/translations/en.json b/src/translations/en.json index a3070c0787b1..c176cf65c96a 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2492,13 +2492,13 @@ "groups": { "entity": { "label": "Entity", - "description": "When something happens to an entity" + "description": "When something happens to an entity." }, "time_location": { "label": "Time and location", "description": "When someone enters or leaves a zone, or at a specific time." }, - "other": { "label": "Other" } + "other": { "label": "Other triggers" } }, "type": { "calendar": { @@ -2534,7 +2534,7 @@ "context_user_picked": "User firing event", "context_user_pick": "Select user", "description": { - "picker": "When an event is being received (event is an advanced concept in Home Assistant)", + "picker": "When an event is being received (event is an advanced concept in Home Assistant).", "full": "When {eventTypes} event is fired" } }, @@ -2546,7 +2546,7 @@ "enter": "Enter", "leave": "Leave", "description": { - "picker": "When an entity created by a geolocation platform appears in or disappears from a zone", + "picker": "When an entity created by a geolocation platform appears in or disappears from a zone.", "full": "When {source} {event, select, \n enter {enters}\n leave {leaves} other {} \n} {zone} {numberOfZones, plural,\n one {zone}\n other {zones}\n}" } }, @@ -2608,7 +2608,7 @@ "updated": "updated" }, "description": { - "picker": "When a persistent notification is added or removed", + "picker": "When a persistent notification is added or removed.", "full": "When a persistent notification is updated" } }, @@ -2619,7 +2619,7 @@ "sunset": "Sunset", "offset": "Offset (optional)", "description": { - "picker": "When the sun sets or rises", + "picker": "When the sun sets or rises.", "sets": "When the sun sets{hasDuration, select, \n true { offset by {duration}} \n other {}\n }", "rises": "When the sun rises{hasDuration, select, \n true { offset by {duration}} \n other {}\n }" } @@ -2648,7 +2648,7 @@ "value_template": "Value template", "for": "For", "description": { - "picker": "When a template is evaluated to true.", + "picker": "When a template evaluates to true.", "full": "When a template changes from false to true{hasDuration, select, \n true { for {duration}} \n other {}\n }" } }, @@ -2669,7 +2669,7 @@ "minutes": "Minutes", "seconds": "Seconds", "description": { - "picker": "Periodically, every defined interval of time." + "picker": "Periodically, at a defined interval." } }, "webhook": { @@ -2692,7 +2692,7 @@ "enter": "Enter", "leave": "Leave", "description": { - "picker": "When someone (or something) enters or leaves a zone", + "picker": "When someone (or something) enters or leaves a zone.", "full": "When {entity} {event, select, \n enter {enters}\n leave {leaves} other {} \n} {zone} {numberOfZones, plural,\n one {zone} \n other {zones}\n}" } } @@ -2734,7 +2734,7 @@ "label": "Time and location", "description": "If someone is in a zone or if the current time is before or after a specified time." }, - "other": { "label": "Other" }, + "other": { "label": "Other conditions" }, "building_blocks": { "label": "Building blocks", "description": "Build more complex conditions." @@ -2766,7 +2766,7 @@ "not": { "label": "Not", "description": { - "picker": "Test if a condition is not true", + "picker": "Test if a condition is not true.", "no_conditions": "Test if no condition matches", "one_condition": "Test if 1 condition does not match", "full": "Test if none of {count} conditions match" @@ -2800,7 +2800,7 @@ "label": "[%key:ui::panel::config::automation::editor::triggers::type::state::label%]", "state": "[%key:ui::panel::config::automation::editor::triggers::type::state::label%]", "description": { - "picker": "If an entity (or attribute) is in a specific state", + "picker": "If an entity (or attribute) is in a specific state.", "no_entity": "Confirm state", "full": "Confirm{hasAttribute, select, \n true { {attribute} of}\n other {}\n} {numberOfEntities, plural,\n zero {an entity is}\n one {{entities} is}\n other {{entities} are}\n} {numberOfStates, plural,\n zero {a state}\n other {{states}}\n}{hasDuration, select, \n true { for {duration}} \n other {}\n }" } @@ -2821,7 +2821,7 @@ "label": "[%key:ui::panel::config::automation::editor::triggers::type::template::label%]", "value_template": "[%key:ui::panel::config::automation::editor::triggers::type::template::value_template%]", "description": { - "picker": "If a template is evaluated to true.", + "picker": "If a template evaluates to true.", "full": "Test if template renders a value equal to true" } }, @@ -2844,7 +2844,7 @@ "sun": "Sunday" }, "description": { - "picker": "If the current time is before or after a specified time", + "picker": "If the current time is before or after a specified time.", "full": "Confirm the {hasTime, select, \n after {time is after {time_after}}\n before {time is before {time_before}}\n after_before {time is after {time_after} and before {time_before}} \n other {}\n }{hasTimeAndDay, select, \n true { and the }\n other {}\n}{hasDay, select, \n true { day is {day}}\n other {}\n}" } }, @@ -2862,7 +2862,7 @@ "entity": "[%key:ui::panel::config::automation::editor::triggers::type::zone::entity%]", "zone": "[%key:ui::panel::config::automation::editor::triggers::type::zone::label%]", "description": { - "picker": "If someone (or something) is in a zone", + "picker": "If someone (or something) is in a zone.", "full": "Confirm {entity} {numberOfEntities, plural,\n one {is}\n other {are}\n} in {zone} {numberOfZones, plural,\n one {zone} \n other {zones}\n} " } } @@ -2899,7 +2899,7 @@ "continue_on_error": "Continue on error", "groups": { "helpers": { "label": "Helpers" }, - "other": { "label": "Other" }, + "other": { "label": "Other actions" }, "building_blocks": { "label": "Building blocks", "description": "Build more complex sequences of actions." @@ -3070,14 +3070,14 @@ "response_variable": "The name of the variable to use as response", "error": "Stop because of an unexpected error", "description": { - "picker": "Stop the sequence of actions", + "picker": "Stop the sequence of actions.", "full": "Stop {hasReason, select, \n true { because: {reason}} \n other {}\n }" } }, "parallel": { "label": "Run in parallel", "description": { - "picker": "perform a sequence of actions in parallel.", + "picker": "Perform a sequence of actions in parallel.", "full": "Run {number} {number, plural,\n one {action}\n other {actions}\n} in parallel" } }, From f099f66065ead07852d268773eecb468523550eb Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 13:36:06 +0100 Subject: [PATCH 030/361] Automation editor tweaks (#19225) * Automation editor tweaks * fix styling --- src/data/condition.ts | 1 - .../add-automation-element-dialog.ts | 145 +++++++++++++----- .../condition/ha-automation-condition.ts | 1 + .../types/ha-automation-condition-device.ts | 1 + .../show-add-automation-element-dialog.ts | 1 + .../types/ha-automation-trigger-device.ts | 1 + 6 files changed, 108 insertions(+), 42 deletions(-) diff --git a/src/data/condition.ts b/src/data/condition.ts index 44a0e218609c..d8c7af44fecc 100644 --- a/src/data/condition.ts +++ b/src/data/condition.ts @@ -46,7 +46,6 @@ export const CONDITION_GROUPS: AutomationElementGroup = { icon: mdiDotsHorizontal, members: { template: {}, - trigger: {}, }, }, } as const; diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index b96283a61dd8..31760dca1bc1 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -1,7 +1,14 @@ import "@material/mwc-list/mwc-list"; import { mdiClose, mdiContentPaste, mdiPlus } from "@mdi/js"; import Fuse, { IFuseOptions } from "fuse.js"; -import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; +import { + CSSResultGroup, + LitElement, + PropertyValues, + css, + html, + nothing, +} from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { ifDefined } from "lit/directives/if-defined"; import { repeat } from "lit/directives/repeat"; @@ -42,6 +49,8 @@ import { AddAutomationElementDialogParams, PASTE_VALUE, } from "./show-add-automation-element-dialog"; +import { computeDomain } from "../../../common/entity/compute_domain"; +import { deepEqual } from "../../../common/util/deep-equal"; const TYPES = { trigger: { groups: TRIGGER_GROUPS, icons: TRIGGER_ICONS }, @@ -93,13 +102,15 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { @state() private _manifests?: DomainManifestLookup; + @state() private _domains?: Set; + @query("ha-dialog") private _dialog?: HaDialog; private _fullScreen = false; - private _width?: number; + @state() private _width?: number; - private _height?: number; + @state() private _height?: number; public showDialog(params): void { this._params = params; @@ -124,6 +135,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { this._prev = undefined; this._filter = ""; this._manifests = undefined; + this._domains = undefined; } private _convertToItem = ( @@ -152,6 +164,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { private _getFilteredItems = memoizeOne( ( type: AddAutomationElementDialogParams["type"], + root: AddAutomationElementDialogParams["root"], group: string | undefined, filter: string, localize: LocalizeFunc, @@ -164,6 +177,10 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { : TYPES[type].groups[group].members! : TYPES[type].groups; + if (type === "condition" && group === "other" && !root) { + groups.trigger = {}; + } + const flattenGroups = (grp: AutomationElementGroup) => Object.entries(grp).map(([key, options]) => options.members @@ -191,7 +208,9 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { private _getGroupItems = memoizeOne( ( type: AddAutomationElementDialogParams["type"], + root: AddAutomationElementDialogParams["root"], group: string | undefined, + domains: Set | undefined, localize: LocalizeFunc, services: HomeAssistant["services"], manifests?: DomainManifestLookup @@ -208,6 +227,10 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { ? TYPES[type].groups[group].members! : TYPES[type].groups; + if (type === "condition" && group === "other" && !root) { + groups.trigger = {}; + } + const result = Object.entries(groups).map(([key, options]) => this._convertToItem(key, options, type, localize) ); @@ -215,15 +238,33 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { if (type === "action") { if (!this._group) { result.unshift( - ...this._serviceGroups(localize, services, manifests, undefined) + ...this._serviceGroups( + localize, + services, + manifests, + domains, + undefined + ) ); } else if (this._group === "helpers") { result.unshift( - ...this._serviceGroups(localize, services, manifests, "helper") + ...this._serviceGroups( + localize, + services, + manifests, + domains, + "helper" + ) ); } else if (this._group === "other") { result.unshift( - ...this._serviceGroups(localize, services, manifests, "other") + ...this._serviceGroups( + localize, + services, + manifests, + domains, + "other" + ) ); } } @@ -243,42 +284,44 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { } ); - private _serviceGroups = memoizeOne( - ( - localize: LocalizeFunc, - services: HomeAssistant["services"], - manifests: DomainManifestLookup | undefined, - type: "helper" | "other" | undefined - ): ListItem[] => { - if (!services || !manifests) { - return []; - } - const result: ListItem[] = []; - Object.keys(services).forEach((domain) => { - const manifest = manifests[domain]; - if ( - (type === undefined && - manifest?.integration_type === "entity" && - !ENTITY_DOMAINS_OTHER.has(domain)) || - (type === "helper" && manifest?.integration_type === "helper") || - (type === "other" && - (ENTITY_DOMAINS_OTHER.has(domain) || - !["helper", "entity"].includes(manifest?.integration_type || ""))) - ) { - result.push({ - group: true, - icon: domainIcon(domain), - key: `${SERVICE_PREFIX}${domain}`, - name: domainToName(localize, domain, manifest), - description: "", - }); - } - }); - return result.sort((a, b) => - stringCompare(a.name, b.name, this.hass.locale.language) - ); + private _serviceGroups = ( + localize: LocalizeFunc, + services: HomeAssistant["services"], + manifests: DomainManifestLookup | undefined, + domains: Set | undefined, + type: "helper" | "other" | undefined + ): ListItem[] => { + if (!services || !manifests) { + return []; } - ); + const result: ListItem[] = []; + Object.keys(services).forEach((domain) => { + const manifest = manifests[domain]; + const domainUsed = !domains ? true : domains.has(domain); + if ( + (type === undefined && + manifest?.integration_type === "entity" && + domainUsed && + !ENTITY_DOMAINS_OTHER.has(domain)) || + (type === "helper" && manifest?.integration_type === "helper") || + (type === "other" && + (ENTITY_DOMAINS_OTHER.has(domain) || + (!domainUsed && manifest?.integration_type === "entity") || + !["helper", "entity"].includes(manifest?.integration_type || ""))) + ) { + result.push({ + group: true, + icon: domainIcon(domain), + key: `${SERVICE_PREFIX}${domain}`, + name: domainToName(localize, domain, manifest), + description: "", + }); + } + }); + return result.sort((a, b) => + stringCompare(a.name, b.name, this.hass.locale.language) + ); + }; private _services = memoizeOne( ( @@ -368,6 +411,19 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { this._height = boundingRect?.height; } + protected willUpdate(changedProperties: PropertyValues): void { + if ( + this._params?.type === "action" && + changedProperties.has("hass") && + changedProperties.get("hass")?.states !== this.hass.states + ) { + const domains = new Set(Object.keys(this.hass.states).map(computeDomain)); + if (!deepEqual(domains, this._domains)) { + this._domains = domains; + } + } + } + protected render() { if (!this._params) { return nothing; @@ -376,6 +432,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { const items = this._filter ? this._getFilteredItems( this._params.type, + this._params.root, this._group, this._filter, this.hass.localize, @@ -384,7 +441,9 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { ) : this._getGroupItems( this._params.type, + this._params.root, this._group, + this._domains, this.hass.localize, this.hass.services, this._manifests @@ -562,6 +621,10 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { ha-icon-next { width: 24px; } + mwc-list { + max-height: 468px; + max-width: 100vw; + } search-input { display: block; margin: 0 16px; diff --git a/src/panels/config/automation/condition/ha-automation-condition.ts b/src/panels/config/automation/condition/ha-automation-condition.ts index 27364b92a3ed..ecf4f8823770 100644 --- a/src/panels/config/automation/condition/ha-automation-condition.ts +++ b/src/panels/config/automation/condition/ha-automation-condition.ts @@ -203,6 +203,7 @@ export default class HaAutomationCondition extends LitElement { showAddAutomationElementDialog(this, { type: "condition", add: this._addCondition, + root: !this.nested, clipboardItem: this._clipboard?.condition?.condition, }); } diff --git a/src/panels/config/automation/condition/types/ha-automation-condition-device.ts b/src/panels/config/automation/condition/types/ha-automation-condition-device.ts index 71568fe02c10..4593a5f70123 100644 --- a/src/panels/config/automation/condition/types/ha-automation-condition-device.ts +++ b/src/panels/config/automation/condition/types/ha-automation-condition-device.ts @@ -168,6 +168,7 @@ export class HaDeviceCondition extends LitElement { } ha-form { + display: block; margin-top: 24px; } `; diff --git a/src/panels/config/automation/show-add-automation-element-dialog.ts b/src/panels/config/automation/show-add-automation-element-dialog.ts index c497ca85c620..55453505121d 100644 --- a/src/panels/config/automation/show-add-automation-element-dialog.ts +++ b/src/panels/config/automation/show-add-automation-element-dialog.ts @@ -6,6 +6,7 @@ export interface AddAutomationElementDialogParams { type: "trigger" | "condition" | "action"; add: (key: string) => void; clipboardItem: string | undefined; + root?: boolean; group?: string; } const loadDialog = () => import("./add-automation-element-dialog"); diff --git a/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts b/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts index 8b3a63575220..1b94ff6138b2 100644 --- a/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts +++ b/src/panels/config/automation/trigger/types/ha-automation-trigger-device.ts @@ -174,6 +174,7 @@ export class HaDeviceTrigger extends LitElement { } ha-form { + display: block; margin-top: 24px; } `; From c125ec087a11c0b584a85b10b6907cae764c9e73 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 16:08:26 +0100 Subject: [PATCH 031/361] Remove references to "service call" from actions (#19226) --- src/components/ha-service-control.ts | 28 ++++++++++++++----- src/data/script.ts | 2 ++ src/data/script_i18n.ts | 5 +++- .../action/ha-automation-action-row.ts | 10 ++++++- .../automation/action/ha-automation-action.ts | 1 + src/translations/en.json | 1 + 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/components/ha-service-control.ts b/src/components/ha-service-control.ts index f1ae8ee54bac..119418355c64 100644 --- a/src/components/ha-service-control.ts +++ b/src/components/ha-service-control.ts @@ -4,7 +4,14 @@ import { HassServices, HassServiceTarget, } from "home-assistant-js-websocket"; -import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit"; +import { + css, + CSSResultGroup, + html, + LitElement, + PropertyValues, + nothing, +} from "lit"; import { customElement, property, query, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { ensureArray } from "../common/array/ensure-array"; @@ -83,6 +90,8 @@ export class HaServiceControl extends LitElement { @property({ type: Boolean }) public showAdvanced?: boolean; + @property({ type: Boolean, reflect: true }) public hidePicker?: boolean; + @state() private _value!: this["value"]; @state() private _checkedKeys = new Set(); @@ -363,12 +372,14 @@ export class HaServiceControl extends LitElement { )) || serviceData?.description; - return html` + return html`${this.hidePicker + ? nothing + : html``}
${description ? html`

${description}

` : ""} ${this._manifest @@ -735,6 +746,9 @@ export class HaServiceControl extends LitElement { margin: var(--service-control-padding, 0 16px); padding: 16px 0; } + :host([hidePicker]) p { + padding-top: 0; + } .checkbox-spacer { width: 32px; } diff --git a/src/data/script.ts b/src/data/script.ts index f0b5e7151b51..08910dc88fcb 100644 --- a/src/data/script.ts +++ b/src/data/script.ts @@ -52,6 +52,7 @@ export const serviceActionStruct: Describe = assign( target: optional(targetStruct), data: optional(object()), response_variable: optional(string()), + metadata: optional(object()), }) ); @@ -133,6 +134,7 @@ export interface ServiceAction extends BaseAction { target?: HassServiceTarget; data?: Record; response_variable?: string; + metadata?: Record; } export interface DeviceAction extends BaseAction { diff --git a/src/data/script_i18n.ts b/src/data/script_i18n.ts index 4b07b84f0ed5..3d7d8c5a1da4 100644 --- a/src/data/script_i18n.ts +++ b/src/data/script_i18n.ts @@ -168,8 +168,11 @@ const tryDescribeAction = ( const service = hass.localize(`component.${domain}.services.${serviceName}.name`) || hass.services[domain][serviceName]?.name; + return hass.localize( - `${actionTranslationBaseKey}.service.description.service_based_on_name`, + `${actionTranslationBaseKey}.service.description.${ + config.metadata ? "service_name" : "service_based_on_name" + }`, { name: service ? `${domainToName(hass.localize, domain)}: ${service}` diff --git a/src/panels/config/automation/action/ha-automation-action-row.ts b/src/panels/config/automation/action/ha-automation-action-row.ts index f09c901c8e1a..0e58c0e8b2b5 100644 --- a/src/panels/config/automation/action/ha-automation-action-row.ts +++ b/src/panels/config/automation/action/ha-automation-action-row.ts @@ -29,6 +29,8 @@ import { classMap } from "lit/directives/class-map"; import { storage } from "../../../../common/decorators/storage"; import { dynamicElement } from "../../../../common/dom/dynamic-element-directive"; import { fireEvent } from "../../../../common/dom/fire_event"; +import { computeDomain } from "../../../../common/entity/compute_domain"; +import { domainIconWithoutDefault } from "../../../../common/entity/domain_icon"; import { capitalizeFirstLetter } from "../../../../common/string/capitalize-first-letter"; import { handleStructError } from "../../../../common/structs/handle-errors"; import "../../../../components/ha-alert"; @@ -190,7 +192,13 @@ export default class HaAutomationActionRow extends LitElement {

${capitalizeFirstLetter( describeAction(this.hass, this._entityReg, this.action) diff --git a/src/panels/config/automation/action/ha-automation-action.ts b/src/panels/config/automation/action/ha-automation-action.ts index dca4bab6acde..ce312a7bd399 100644 --- a/src/panels/config/automation/action/ha-automation-action.ts +++ b/src/panels/config/automation/action/ha-automation-action.ts @@ -191,6 +191,7 @@ export default class HaAutomationAction extends LitElement { } else if (isService(action)) { actions = this.actions.concat({ service: getService(action), + metadata: {}, }); } else { const elClass = customElements.get( diff --git a/src/translations/en.json b/src/translations/en.json index c176cf65c96a..e771c8fe1910 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2914,6 +2914,7 @@ "description": { "service_based_on_template": "Call a service based on a template on {targets}", "service_based_on_name": "Call a service ''{name}'' on {targets}", + "service_name": "''{name}'' on {targets}", "service": "Call a service", "target_template": "templated {name}", "target_unknown_entity": "unknown entity", From f2226cdec24760fce2172978f97a07b609675372 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 18:11:34 +0100 Subject: [PATCH 032/361] Use brand icons in actions (#19227) --- src/common/const.ts | 4 ++ .../add-automation-element-dialog.ts | 39 ++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/common/const.ts b/src/common/const.ts index 66c14e64e140..68f4fa97b1c1 100644 --- a/src/common/const.ts +++ b/src/common/const.ts @@ -29,6 +29,7 @@ import { mdiFlash, mdiFlower, mdiFormatListBulleted, + mdiFormatListCheckbox, mdiFormTextbox, mdiGauge, mdiGoogleAssistant, @@ -64,6 +65,7 @@ import { mdiTransmissionTower, mdiWater, mdiWaterPercent, + mdiWeatherPartlyCloudy, mdiWeatherPouring, mdiWeatherRainy, mdiWeatherWindy, @@ -128,6 +130,7 @@ export const FIXED_DOMAIN_ICONS = { updater: mdiCloudUpload, vacuum: mdiRobotVacuum, wake_word: mdiChatSleep, + weather: mdiWeatherPartlyCloudy, zone: mdiMapMarkerRadius, }; @@ -166,6 +169,7 @@ export const FIXED_DEVICE_CLASS_ICONS = { precipitation_intensity: mdiWeatherPouring, pressure: mdiGauge, reactive_power: mdiFlash, + shopping_List: mdiFormatListCheckbox, signal_strength: mdiWifi, sound_pressure: mdiEarHearing, speed: mdiSpeedometer, diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index 31760dca1bc1..0e930b7c9916 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -15,7 +15,7 @@ import { repeat } from "lit/directives/repeat"; import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../common/dom/fire_event"; -import { domainIcon } from "../../../common/entity/domain_icon"; +import { domainIconWithoutDefault } from "../../../common/entity/domain_icon"; import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event"; import { stringCompare } from "../../../common/string/compare"; import { LocalizeFunc } from "../../../common/translations/localize"; @@ -45,6 +45,7 @@ import { TRIGGER_GROUPS, TRIGGER_ICONS } from "../../../data/trigger"; import { HassDialog } from "../../../dialogs/make-dialog-manager"; import { haStyle, haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; +import { brandsUrl } from "../../../util/brands-url"; import { AddAutomationElementDialogParams, PASTE_VALUE, @@ -68,7 +69,8 @@ interface ListItem { key: string; name: string; description: string; - icon: string; + icon?: string; + image?: string; group: boolean; } @@ -309,9 +311,17 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { (!domainUsed && manifest?.integration_type === "entity") || !["helper", "entity"].includes(manifest?.integration_type || ""))) ) { + const icon = domainIconWithoutDefault(domain); result.push({ group: true, - icon: domainIcon(domain), + icon, + image: !icon + ? brandsUrl({ + domain, + type: "icon", + darkOptimized: this.hass.themes?.darkMode, + }) + : undefined, key: `${SERVICE_PREFIX}${domain}`, name: domainToName(localize, domain, manifest), description: "", @@ -345,9 +355,17 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { const services_keys = Object.keys(services[dmn]); for (const service of services_keys) { + const icon = domainIconWithoutDefault(dmn); result.push({ group: false, - icon: domainIcon(dmn), + icon, + image: !icon + ? brandsUrl({ + domain: dmn, + type: "icon", + darkOptimized: this.hass.themes?.darkMode, + }) + : undefined, key: `${SERVICE_PREFIX}${dmn}.${service}`, name: `${domain ? "" : `${domainToName(localize, dmn)}: `}${ this.hass.localize(`component.${dmn}.services.${service}.name`) || @@ -556,7 +574,18 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { > ${item.name} ${item.description} - + ${item.icon + ? html`` + : html``} ${item.group ? html`` : html` Date: Tue, 2 Jan 2024 18:31:18 +0100 Subject: [PATCH 033/361] Change format of service description (#19229) --- src/data/script_i18n.ts | 15 ++++++++++++--- src/translations/en.json | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/data/script_i18n.ts b/src/data/script_i18n.ts index 3d7d8c5a1da4..40c823bc862f 100644 --- a/src/data/script_i18n.ts +++ b/src/data/script_i18n.ts @@ -169,10 +169,19 @@ const tryDescribeAction = ( hass.localize(`component.${domain}.services.${serviceName}.name`) || hass.services[domain][serviceName]?.name; + if (config.metadata) { + return hass.localize( + `${actionTranslationBaseKey}.service.description.service_name`, + { + domain: domainToName(hass.localize, domain), + name: service || config.service, + targets: formatListWithAnds(hass.locale, targets), + } + ); + } + return hass.localize( - `${actionTranslationBaseKey}.service.description.${ - config.metadata ? "service_name" : "service_based_on_name" - }`, + `${actionTranslationBaseKey}.service.description.service_based_on_name`, { name: service ? `${domainToName(hass.localize, domain)}: ${service}` diff --git a/src/translations/en.json b/src/translations/en.json index e771c8fe1910..6ef41c81c129 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2914,7 +2914,7 @@ "description": { "service_based_on_template": "Call a service based on a template on {targets}", "service_based_on_name": "Call a service ''{name}'' on {targets}", - "service_name": "''{name}'' on {targets}", + "service_name": "{domain} ''{name}'' on {targets}", "service": "Call a service", "target_template": "templated {name}", "target_unknown_entity": "unknown entity", From 18b5fd59a629268bce2d5d7aa6e7fd390e1d6ab1 Mon Sep 17 00:00:00 2001 From: Josh McCarty Date: Tue, 2 Jan 2024 10:35:08 -0700 Subject: [PATCH 034/361] Add missing device classes for entity-registry-settings-editor (#19231) * Add connectivity device class for binary sensors * Add update device class * Separate connectivity and update --- src/panels/config/entities/entity-registry-settings-editor.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/panels/config/entities/entity-registry-settings-editor.ts b/src/panels/config/entities/entity-registry-settings-editor.ts index 14d88e12afc7..9e7213e41475 100644 --- a/src/panels/config/entities/entity-registry-settings-editor.ts +++ b/src/panels/config/entities/entity-registry-settings-editor.ts @@ -118,6 +118,8 @@ const OVERRIDE_DEVICE_CLASSES = { "carbon_monoxide", "moisture", ], // Alarm + ["connectivity"], // Connectivity + ["update"], // Update ], }; From 01bd88ce101c1c0909c093d55afdaab1cd24073d Mon Sep 17 00:00:00 2001 From: JLo Date: Tue, 2 Jan 2024 18:39:55 +0100 Subject: [PATCH 035/361] New copy for device trigger in automation editor (#19232) New copy for device trigger in automation editor: "Set of conditions provided by your device. Great way to start." --- src/translations/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/translations/en.json b/src/translations/en.json index 6ef41c81c129..53306cd8b77d 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2760,7 +2760,7 @@ "preset_mode": "Preset mode" }, "description": { - "picker": "If a device is in a certain state. Great way to start." + "picker": "Set of conditions provided by your device. Great way to start." } }, "not": { From f994b378f1be438ae46730412b1cc6109ee71490 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 18:47:39 +0100 Subject: [PATCH 036/361] Update add-automation-element-dialog.ts --- src/panels/config/automation/add-automation-element-dialog.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index 0e930b7c9916..d498e8375cd8 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -528,7 +528,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { rootTabbable style=${styleMap({ width: this._width ? `${this._width}px` : "auto", - height: this._height ? `${Math.min(468, this._height)}px` : "auto", + height: this._height ? `${Math.min(670, this._height)}px` : "auto", })} > ${this._params.clipboardItem && @@ -651,7 +651,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { width: 24px; } mwc-list { - max-height: 468px; + max-height: 670px; max-width: 100vw; } search-input { From 8d496e1511c0ed56116da4829141239ef92e0423 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 18:47:39 +0100 Subject: [PATCH 037/361] Update add-automation-element-dialog.ts --- src/panels/config/automation/add-automation-element-dialog.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index 0e930b7c9916..d498e8375cd8 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -528,7 +528,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { rootTabbable style=${styleMap({ width: this._width ? `${this._width}px` : "auto", - height: this._height ? `${Math.min(468, this._height)}px` : "auto", + height: this._height ? `${Math.min(670, this._height)}px` : "auto", })} > ${this._params.clipboardItem && @@ -651,7 +651,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { width: 24px; } mwc-list { - max-height: 468px; + max-height: 670px; max-width: 100vw; } search-input { From 5eaa6dafd902b2abdce044bb67fe772ad36cd573 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 18:48:34 +0100 Subject: [PATCH 038/361] Give todo and calendar edit static header (#19233) --- src/panels/calendar/dialog-calendar-event-editor.ts | 6 +++--- src/panels/todo/dialog-todo-item-editor.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/panels/calendar/dialog-calendar-event-editor.ts b/src/panels/calendar/dialog-calendar-event-editor.ts index 7c06cac92cf1..e5925b1243e2 100644 --- a/src/panels/calendar/dialog-calendar-event-editor.ts +++ b/src/panels/calendar/dialog-calendar-event-editor.ts @@ -144,9 +144,9 @@ class DialogCalendarEventEditor extends LitElement { escapeKeyAction .heading=${createCloseHeading( this.hass, - isCreate - ? this.hass.localize("ui.components.calendar.event.add") - : this._summary + this.hass.localize( + `ui.components.calendar.event.${isCreate ? "add" : "edit"}` + ) )} >
diff --git a/src/panels/todo/dialog-todo-item-editor.ts b/src/panels/todo/dialog-todo-item-editor.ts index c81b9e4dbec3..cd26ad35fc28 100644 --- a/src/panels/todo/dialog-todo-item-editor.ts +++ b/src/panels/todo/dialog-todo-item-editor.ts @@ -101,9 +101,9 @@ class DialogTodoItemEditor extends LitElement { scrimClickAction .heading=${createCloseHeading( this.hass, - isCreate - ? this.hass.localize("ui.components.todo.item.add") - : this._summary + this.hass.localize( + `ui.components.todo.item.${isCreate ? "add" : "edit"}` + ) )} >
From de3b9a5bb2a847cc7353ec9e960a83363b57ba25 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 18:48:34 +0100 Subject: [PATCH 039/361] Give todo and calendar edit static header (#19233) --- src/panels/calendar/dialog-calendar-event-editor.ts | 6 +++--- src/panels/todo/dialog-todo-item-editor.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/panels/calendar/dialog-calendar-event-editor.ts b/src/panels/calendar/dialog-calendar-event-editor.ts index 7c06cac92cf1..e5925b1243e2 100644 --- a/src/panels/calendar/dialog-calendar-event-editor.ts +++ b/src/panels/calendar/dialog-calendar-event-editor.ts @@ -144,9 +144,9 @@ class DialogCalendarEventEditor extends LitElement { escapeKeyAction .heading=${createCloseHeading( this.hass, - isCreate - ? this.hass.localize("ui.components.calendar.event.add") - : this._summary + this.hass.localize( + `ui.components.calendar.event.${isCreate ? "add" : "edit"}` + ) )} >
diff --git a/src/panels/todo/dialog-todo-item-editor.ts b/src/panels/todo/dialog-todo-item-editor.ts index c81b9e4dbec3..cd26ad35fc28 100644 --- a/src/panels/todo/dialog-todo-item-editor.ts +++ b/src/panels/todo/dialog-todo-item-editor.ts @@ -101,9 +101,9 @@ class DialogTodoItemEditor extends LitElement { scrimClickAction .heading=${createCloseHeading( this.hass, - isCreate - ? this.hass.localize("ui.components.todo.item.add") - : this._summary + this.hass.localize( + `ui.components.todo.item.${isCreate ? "add" : "edit"}` + ) )} >
From 7d412a9913defcf67b59d04ea49c7eebf497d745 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 18:49:31 +0100 Subject: [PATCH 040/361] Bumped version to 20240102.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d1e5abd3d1c4..7d09a1121ede 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240101.0" +version = "20240102.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From 53dedc6c6587b2eeb9f76b53f55ccb5129e99612 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 18:49:31 +0100 Subject: [PATCH 041/361] Bumped version to 20240102.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d1e5abd3d1c4..7d09a1121ede 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240101.0" +version = "20240102.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From 2933d642edfb5250b140e8154d6ff15eccf4f902 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 2 Jan 2024 13:55:44 -0500 Subject: [PATCH 042/361] Update dependency @bundle-stats/plugin-webpack-filter to v4.8.4 (#19230) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 7b3ad9c6a114..663a412014d2 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "@babel/plugin-transform-runtime": "7.23.7", "@babel/preset-env": "7.23.7", "@babel/preset-typescript": "7.23.3", - "@bundle-stats/plugin-webpack-filter": "4.8.3", + "@bundle-stats/plugin-webpack-filter": "4.8.4", "@koa/cors": "5.0.0", "@lokalise/node-api": "12.1.0", "@octokit/auth-oauth-device": "6.0.1", diff --git a/yarn.lock b/yarn.lock index dd2a90537271..2f9b96e6b6ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1448,12 +1448,12 @@ __metadata: languageName: node linkType: hard -"@bundle-stats/plugin-webpack-filter@npm:4.8.3": - version: 4.8.3 - resolution: "@bundle-stats/plugin-webpack-filter@npm:4.8.3" +"@bundle-stats/plugin-webpack-filter@npm:4.8.4": + version: 4.8.4 + resolution: "@bundle-stats/plugin-webpack-filter@npm:4.8.4" peerDependencies: core-js: ^3.0.0 - checksum: a832be786197b0cd534e4ccb35cd7230f322b2b77697f5f4ac0b098e51f7867bff0364020f6015d31f2963619e1408933454841baac035452a9fec37d921f841 + checksum: 7a33a19094fb32579ca215cfee7c536a7e524558e6a17bee0376377691b4957bd1346531dfe3b01e8daf364acef75e1926f3d1aed76d986be79ba374157782fb languageName: node linkType: hard @@ -9519,7 +9519,7 @@ __metadata: "@babel/preset-typescript": "npm:7.23.3" "@babel/runtime": "npm:7.23.7" "@braintree/sanitize-url": "npm:7.0.0" - "@bundle-stats/plugin-webpack-filter": "npm:4.8.3" + "@bundle-stats/plugin-webpack-filter": "npm:4.8.4" "@codemirror/autocomplete": "npm:6.11.1" "@codemirror/commands": "npm:6.3.2" "@codemirror/language": "npm:6.9.3" From e72148175725b29a28dc216fd3eeb4d28c11729b Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 19:58:37 +0100 Subject: [PATCH 043/361] Move notification services to main list (#19235) --- .../config/automation/add-automation-element-dialog.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index d498e8375cd8..06a77884f1c6 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -90,6 +90,8 @@ const ENTITY_DOMAINS_OTHER = new Set([ "image_processing", ]); +const ENTITY_DOMAINS_MAIN = new Set(["notify"]); + @customElement("add-automation-element-dialog") class DialogAddAutomationElement extends LitElement implements HassDialog { @property({ attribute: false }) public hass!: HomeAssistant; @@ -302,11 +304,13 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { const domainUsed = !domains ? true : domains.has(domain); if ( (type === undefined && - manifest?.integration_type === "entity" && - domainUsed && - !ENTITY_DOMAINS_OTHER.has(domain)) || + (ENTITY_DOMAINS_MAIN.has(domain) || + (manifest?.integration_type === "entity" && + domainUsed && + !ENTITY_DOMAINS_OTHER.has(domain)))) || (type === "helper" && manifest?.integration_type === "helper") || (type === "other" && + !ENTITY_DOMAINS_MAIN.has(domain) && (ENTITY_DOMAINS_OTHER.has(domain) || (!domainUsed && manifest?.integration_type === "entity") || !["helper", "entity"].includes(manifest?.integration_type || ""))) From 8a8b04ed004a3927ead29d5b80e7689d8f73951f Mon Sep 17 00:00:00 2001 From: Simon Lamon <32477463+silamon@users.noreply.github.com> Date: Tue, 2 Jan 2024 20:00:19 +0100 Subject: [PATCH 044/361] Set default values for required and disabled for labeled slider (#19246) Set default values --- src/components/ha-labeled-slider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ha-labeled-slider.ts b/src/components/ha-labeled-slider.ts index 366eb4f5555c..5faf7a8b96b2 100644 --- a/src/components/ha-labeled-slider.ts +++ b/src/components/ha-labeled-slider.ts @@ -10,9 +10,9 @@ class HaLabeledSlider extends LitElement { @property() public caption?: string; - @property() public disabled?: boolean; + @property({ type: Boolean }) public disabled = false; - @property() public required?: boolean; + @property({ type: Boolean }) public required = true; @property() public min: number = 0; From 7354988ec96e1abf1e96dc4df755cf4ea0c4e599 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 2 Jan 2024 19:58:37 +0100 Subject: [PATCH 045/361] Move notification services to main list (#19235) --- .../config/automation/add-automation-element-dialog.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index d498e8375cd8..06a77884f1c6 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -90,6 +90,8 @@ const ENTITY_DOMAINS_OTHER = new Set([ "image_processing", ]); +const ENTITY_DOMAINS_MAIN = new Set(["notify"]); + @customElement("add-automation-element-dialog") class DialogAddAutomationElement extends LitElement implements HassDialog { @property({ attribute: false }) public hass!: HomeAssistant; @@ -302,11 +304,13 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { const domainUsed = !domains ? true : domains.has(domain); if ( (type === undefined && - manifest?.integration_type === "entity" && - domainUsed && - !ENTITY_DOMAINS_OTHER.has(domain)) || + (ENTITY_DOMAINS_MAIN.has(domain) || + (manifest?.integration_type === "entity" && + domainUsed && + !ENTITY_DOMAINS_OTHER.has(domain)))) || (type === "helper" && manifest?.integration_type === "helper") || (type === "other" && + !ENTITY_DOMAINS_MAIN.has(domain) && (ENTITY_DOMAINS_OTHER.has(domain) || (!domainUsed && manifest?.integration_type === "entity") || !["helper", "entity"].includes(manifest?.integration_type || ""))) From c2f3e43ee50fcabd26254ebd3412217b6f49a045 Mon Sep 17 00:00:00 2001 From: Simon Lamon <32477463+silamon@users.noreply.github.com> Date: Tue, 2 Jan 2024 20:00:19 +0100 Subject: [PATCH 046/361] Set default values for required and disabled for labeled slider (#19246) Set default values --- src/components/ha-labeled-slider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ha-labeled-slider.ts b/src/components/ha-labeled-slider.ts index 366eb4f5555c..5faf7a8b96b2 100644 --- a/src/components/ha-labeled-slider.ts +++ b/src/components/ha-labeled-slider.ts @@ -10,9 +10,9 @@ class HaLabeledSlider extends LitElement { @property() public caption?: string; - @property() public disabled?: boolean; + @property({ type: Boolean }) public disabled = false; - @property() public required?: boolean; + @property({ type: Boolean }) public required = true; @property() public min: number = 0; From 46565715c9fb46273d22292c7cc245b0b69dd12e Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 10:37:30 +0100 Subject: [PATCH 047/361] Calculate used domains on open of action dialog (#19255) --- .../automation/add-automation-element-dialog.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index 06a77884f1c6..f8be65baf183 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -122,6 +122,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { if (this._params?.type === "action") { this.hass.loadBackendTranslation("services"); this._fetchManifests(); + this._calculateUsedDomains(); } this._fullScreen = matchMedia( "all and (max-width: 450px), all and (max-height: 500px)" @@ -425,6 +426,13 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { this._manifests = manifests; } + private _calculateUsedDomains() { + const domains = new Set(Object.keys(this.hass.states).map(computeDomain)); + if (!deepEqual(domains, this._domains)) { + this._domains = domains; + } + } + protected _opened(): void { // Store the width and height so that when we search, box doesn't jump const boundingRect = @@ -439,10 +447,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { changedProperties.has("hass") && changedProperties.get("hass")?.states !== this.hass.states ) { - const domains = new Set(Object.keys(this.hass.states).map(computeDomain)); - if (!deepEqual(domains, this._domains)) { - this._domains = domains; - } + this._calculateUsedDomains(); } } From c7a98fa5a1f25b283dfcff91ef4efb4a697372e9 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 10:37:59 +0100 Subject: [PATCH 048/361] Bumped version to 20240103.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7d09a1121ede..f43e4cf0dc55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240102.0" +version = "20240103.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From 8ee4aa9e634a2f391b4aa51f2a9cfeb116ce77d8 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 10:37:59 +0100 Subject: [PATCH 049/361] Bumped version to 20240103.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7d09a1121ede..f43e4cf0dc55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240102.0" +version = "20240103.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From 6e7366bf690f500f9cfa4f81aefd002c822dc9ed Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 10:37:30 +0100 Subject: [PATCH 050/361] Calculate used domains on open of action dialog (#19255) --- .../automation/add-automation-element-dialog.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index 06a77884f1c6..f8be65baf183 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -122,6 +122,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { if (this._params?.type === "action") { this.hass.loadBackendTranslation("services"); this._fetchManifests(); + this._calculateUsedDomains(); } this._fullScreen = matchMedia( "all and (max-width: 450px), all and (max-height: 500px)" @@ -425,6 +426,13 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { this._manifests = manifests; } + private _calculateUsedDomains() { + const domains = new Set(Object.keys(this.hass.states).map(computeDomain)); + if (!deepEqual(domains, this._domains)) { + this._domains = domains; + } + } + protected _opened(): void { // Store the width and height so that when we search, box doesn't jump const boundingRect = @@ -439,10 +447,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { changedProperties.has("hass") && changedProperties.get("hass")?.states !== this.hass.states ) { - const domains = new Set(Object.keys(this.hass.states).map(computeDomain)); - if (!deepEqual(domains, this._domains)) { - this._domains = domains; - } + this._calculateUsedDomains(); } } From 29fefa1d602c2c1912a2e02afbaed9f80010cca9 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 12:20:11 +0100 Subject: [PATCH 051/361] Revert conditional rendering of condition (#19257) * Fix conditionally showing `triggered by` * revert conditional rendering * Update add-automation-element-dialog.ts * Update add-automation-element-dialog.ts --- src/data/condition.ts | 1 + .../add-automation-element-dialog.ts | 43 ++++++++----------- .../condition/ha-automation-condition.ts | 1 - .../show-add-automation-element-dialog.ts | 1 - 4 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/data/condition.ts b/src/data/condition.ts index d8c7af44fecc..44a0e218609c 100644 --- a/src/data/condition.ts +++ b/src/data/condition.ts @@ -46,6 +46,7 @@ export const CONDITION_GROUPS: AutomationElementGroup = { icon: mdiDotsHorizontal, members: { template: {}, + trigger: {}, }, }, } as const; diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index f8be65baf183..cf5874f80cd8 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -143,6 +143,16 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { this._domains = undefined; } + private _getGroups = ( + type: AddAutomationElementDialogParams["type"], + group: string | undefined + ): AutomationElementGroup => + group + ? isService(group) + ? {} + : TYPES[type].groups[group].members! + : TYPES[type].groups; + private _convertToItem = ( key: string, options, @@ -169,22 +179,13 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { private _getFilteredItems = memoizeOne( ( type: AddAutomationElementDialogParams["type"], - root: AddAutomationElementDialogParams["root"], group: string | undefined, filter: string, localize: LocalizeFunc, services: HomeAssistant["services"], manifests?: DomainManifestLookup ): ListItem[] => { - const groups: AutomationElementGroup = group - ? isService(group) - ? {} - : TYPES[type].groups[group].members! - : TYPES[type].groups; - - if (type === "condition" && group === "other" && !root) { - groups.trigger = {}; - } + const groups = this._getGroups(type, group); const flattenGroups = (grp: AutomationElementGroup) => Object.entries(grp).map(([key, options]) => @@ -213,7 +214,6 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { private _getGroupItems = memoizeOne( ( type: AddAutomationElementDialogParams["type"], - root: AddAutomationElementDialogParams["root"], group: string | undefined, domains: Set | undefined, localize: LocalizeFunc, @@ -221,20 +221,17 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { manifests?: DomainManifestLookup ): ListItem[] => { if (type === "action" && isService(group)) { - const result = this._services(localize, services, manifests, group); + let result = this._services(localize, services, manifests, group); if (group === `${SERVICE_PREFIX}media_player`) { - result.unshift(this._convertToItem("play_media", {}, type, localize)); + result = [ + this._convertToItem("play_media", {}, type, localize), + ...result, + ]; } return result; } - const groups: AutomationElementGroup = group - ? TYPES[type].groups[group].members! - : TYPES[type].groups; - - if (type === "condition" && group === "other" && !root) { - groups.trigger = {}; - } + const groups = this._getGroups(type, group); const result = Object.entries(groups).map(([key, options]) => this._convertToItem(key, options, type, localize) @@ -459,7 +456,6 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { const items = this._filter ? this._getFilteredItems( this._params.type, - this._params.root, this._group, this._filter, this.hass.localize, @@ -468,7 +464,6 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { ) : this._getGroupItems( this._params.type, - this._params.root, this._group, this._domains, this.hass.localize, @@ -537,7 +532,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { rootTabbable style=${styleMap({ width: this._width ? `${this._width}px` : "auto", - height: this._height ? `${Math.min(670, this._height)}px` : "auto", + height: this._height ? `${Math.min(468, this._height)}px` : "auto", })} > ${this._params.clipboardItem && @@ -660,7 +655,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { width: 24px; } mwc-list { - max-height: 670px; + max-height: 468px; max-width: 100vw; } search-input { diff --git a/src/panels/config/automation/condition/ha-automation-condition.ts b/src/panels/config/automation/condition/ha-automation-condition.ts index ecf4f8823770..27364b92a3ed 100644 --- a/src/panels/config/automation/condition/ha-automation-condition.ts +++ b/src/panels/config/automation/condition/ha-automation-condition.ts @@ -203,7 +203,6 @@ export default class HaAutomationCondition extends LitElement { showAddAutomationElementDialog(this, { type: "condition", add: this._addCondition, - root: !this.nested, clipboardItem: this._clipboard?.condition?.condition, }); } diff --git a/src/panels/config/automation/show-add-automation-element-dialog.ts b/src/panels/config/automation/show-add-automation-element-dialog.ts index 55453505121d..c497ca85c620 100644 --- a/src/panels/config/automation/show-add-automation-element-dialog.ts +++ b/src/panels/config/automation/show-add-automation-element-dialog.ts @@ -6,7 +6,6 @@ export interface AddAutomationElementDialogParams { type: "trigger" | "condition" | "action"; add: (key: string) => void; clipboardItem: string | undefined; - root?: boolean; group?: string; } const loadDialog = () => import("./add-automation-element-dialog"); From 6224cb69941b22c3b14ee6b622d338460cd85623 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 12:28:46 +0100 Subject: [PATCH 052/361] Bumped version to 20240103.1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f43e4cf0dc55..570bc96eaf74 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240103.0" +version = "20240103.1" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From c9a0ae6e2d35488304c5ad0a62b528e4c64fe615 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 12:28:46 +0100 Subject: [PATCH 053/361] Bumped version to 20240103.1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f43e4cf0dc55..570bc96eaf74 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240103.0" +version = "20240103.1" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From 336214d97f3715a866988a257edf939ec37b25d5 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 12:20:11 +0100 Subject: [PATCH 054/361] Revert conditional rendering of condition (#19257) * Fix conditionally showing `triggered by` * revert conditional rendering * Update add-automation-element-dialog.ts * Update add-automation-element-dialog.ts --- src/data/condition.ts | 1 + .../add-automation-element-dialog.ts | 43 ++++++++----------- .../condition/ha-automation-condition.ts | 1 - .../show-add-automation-element-dialog.ts | 1 - 4 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/data/condition.ts b/src/data/condition.ts index d8c7af44fecc..44a0e218609c 100644 --- a/src/data/condition.ts +++ b/src/data/condition.ts @@ -46,6 +46,7 @@ export const CONDITION_GROUPS: AutomationElementGroup = { icon: mdiDotsHorizontal, members: { template: {}, + trigger: {}, }, }, } as const; diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index f8be65baf183..cf5874f80cd8 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -143,6 +143,16 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { this._domains = undefined; } + private _getGroups = ( + type: AddAutomationElementDialogParams["type"], + group: string | undefined + ): AutomationElementGroup => + group + ? isService(group) + ? {} + : TYPES[type].groups[group].members! + : TYPES[type].groups; + private _convertToItem = ( key: string, options, @@ -169,22 +179,13 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { private _getFilteredItems = memoizeOne( ( type: AddAutomationElementDialogParams["type"], - root: AddAutomationElementDialogParams["root"], group: string | undefined, filter: string, localize: LocalizeFunc, services: HomeAssistant["services"], manifests?: DomainManifestLookup ): ListItem[] => { - const groups: AutomationElementGroup = group - ? isService(group) - ? {} - : TYPES[type].groups[group].members! - : TYPES[type].groups; - - if (type === "condition" && group === "other" && !root) { - groups.trigger = {}; - } + const groups = this._getGroups(type, group); const flattenGroups = (grp: AutomationElementGroup) => Object.entries(grp).map(([key, options]) => @@ -213,7 +214,6 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { private _getGroupItems = memoizeOne( ( type: AddAutomationElementDialogParams["type"], - root: AddAutomationElementDialogParams["root"], group: string | undefined, domains: Set | undefined, localize: LocalizeFunc, @@ -221,20 +221,17 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { manifests?: DomainManifestLookup ): ListItem[] => { if (type === "action" && isService(group)) { - const result = this._services(localize, services, manifests, group); + let result = this._services(localize, services, manifests, group); if (group === `${SERVICE_PREFIX}media_player`) { - result.unshift(this._convertToItem("play_media", {}, type, localize)); + result = [ + this._convertToItem("play_media", {}, type, localize), + ...result, + ]; } return result; } - const groups: AutomationElementGroup = group - ? TYPES[type].groups[group].members! - : TYPES[type].groups; - - if (type === "condition" && group === "other" && !root) { - groups.trigger = {}; - } + const groups = this._getGroups(type, group); const result = Object.entries(groups).map(([key, options]) => this._convertToItem(key, options, type, localize) @@ -459,7 +456,6 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { const items = this._filter ? this._getFilteredItems( this._params.type, - this._params.root, this._group, this._filter, this.hass.localize, @@ -468,7 +464,6 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { ) : this._getGroupItems( this._params.type, - this._params.root, this._group, this._domains, this.hass.localize, @@ -537,7 +532,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { rootTabbable style=${styleMap({ width: this._width ? `${this._width}px` : "auto", - height: this._height ? `${Math.min(670, this._height)}px` : "auto", + height: this._height ? `${Math.min(468, this._height)}px` : "auto", })} > ${this._params.clipboardItem && @@ -660,7 +655,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { width: 24px; } mwc-list { - max-height: 670px; + max-height: 468px; max-width: 100vw; } search-input { diff --git a/src/panels/config/automation/condition/ha-automation-condition.ts b/src/panels/config/automation/condition/ha-automation-condition.ts index ecf4f8823770..27364b92a3ed 100644 --- a/src/panels/config/automation/condition/ha-automation-condition.ts +++ b/src/panels/config/automation/condition/ha-automation-condition.ts @@ -203,7 +203,6 @@ export default class HaAutomationCondition extends LitElement { showAddAutomationElementDialog(this, { type: "condition", add: this._addCondition, - root: !this.nested, clipboardItem: this._clipboard?.condition?.condition, }); } diff --git a/src/panels/config/automation/show-add-automation-element-dialog.ts b/src/panels/config/automation/show-add-automation-element-dialog.ts index 55453505121d..c497ca85c620 100644 --- a/src/panels/config/automation/show-add-automation-element-dialog.ts +++ b/src/panels/config/automation/show-add-automation-element-dialog.ts @@ -6,7 +6,6 @@ export interface AddAutomationElementDialogParams { type: "trigger" | "condition" | "action"; add: (key: string) => void; clipboardItem: string | undefined; - root?: boolean; group?: string; } const loadDialog = () => import("./add-automation-element-dialog"); From acbb7e0453e20da93e536aa5c5d8d122cdfdb46e Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 3 Jan 2024 14:26:40 +0100 Subject: [PATCH 055/361] Display edit button for climate fan mode feature (#19259) --- .../lovelace/editor/config-elements/hui-card-features-editor.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts b/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts index 49290ba57102..8693be890d8d 100644 --- a/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts @@ -81,6 +81,7 @@ const EDITABLES_FEATURE_TYPES = new Set([ "humidifier-modes", "water-heater-operation-modes", "lawn-mower-commands", + "climate-fan-modes", "climate-preset-modes", "numeric-input", "update-actions", From 8368fb44081a20a78f01ce76b770bdbb0bb1a826 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 14:58:36 +0100 Subject: [PATCH 056/361] Fix checking todo item that dont support due date (#19262) * Fix checking todo item that dont support due date * make cleaner * Revert "make cleaner" This reverts commit fa33b3361451dd334d9f69142f9754a1ea2c1ca4. * Update dialog-todo-item-editor.ts * do check in 1 place --- src/data/todo.ts | 12 +++++++++--- src/panels/lovelace/cards/hui-todo-list-card.ts | 3 ++- src/panels/todo/dialog-todo-item-editor.ts | 12 +++++++++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/data/todo.ts b/src/data/todo.ts index 9af8ef0f4cc6..659c8d0c3c24 100644 --- a/src/data/todo.ts +++ b/src/data/todo.ts @@ -83,9 +83,12 @@ export const updateItem = ( item: item.uid, rename: item.summary, status: item.status, - description: item.description || null, + description: item.description, due_datetime: item.due?.includes("T") ? item.due : undefined, - due_date: item.due?.includes("T") ? undefined : item.due || null, + due_date: + item.due === undefined || item.due?.includes("T") + ? undefined + : item.due, }, { entity_id } ); @@ -102,7 +105,10 @@ export const createItem = ( item: item.summary, description: item.description || undefined, due_datetime: item.due?.includes("T") ? item.due : undefined, - due_date: item.due?.includes("T") ? undefined : item.due, + due_date: + item.due === undefined || item.due?.includes("T") + ? undefined + : item.due, }, { entity_id } ); diff --git a/src/panels/lovelace/cards/hui-todo-list-card.ts b/src/panels/lovelace/cards/hui-todo-list-card.ts index 3352f7a42b43..d1d62880f8ed 100644 --- a/src/panels/lovelace/cards/hui-todo-list-card.ts +++ b/src/panels/lovelace/cards/hui-todo-list-card.ts @@ -476,7 +476,8 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard { return; } await updateItem(this.hass!, this._entityId!, { - ...item, + uid: item.uid, + summary: item.summary, status: item.status === TodoItemStatus.NeedsAction ? TodoItemStatus.Completed diff --git a/src/panels/todo/dialog-todo-item-editor.ts b/src/panels/todo/dialog-todo-item-editor.ts index cd26ad35fc28..daa5eff68627 100644 --- a/src/panels/todo/dialog-todo-item-editor.ts +++ b/src/panels/todo/dialog-todo-item-editor.ts @@ -324,14 +324,20 @@ class DialogTodoItemEditor extends LitElement { (this._todoListSupportsFeature( TodoListEntityFeature.SET_DESCRIPTION_ON_ITEM ) - ? // backend should accept null to clear the field, but it doesn't now - null + ? null : undefined), due: this._due ? this._hasTime ? this._due.toISOString() : this._formatDate(this._due) - : null, + : this._todoListSupportsFeature( + TodoListEntityFeature.SET_DUE_DATETIME_ON_ITEM + ) || + this._todoListSupportsFeature( + TodoListEntityFeature.SET_DUE_DATE_ON_ITEM + ) + ? null + : undefined, status: this._checked ? TodoItemStatus.Completed : TodoItemStatus.NeedsAction, From 41bb677ebe86531e76b4aca5610bc56727c477fc Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Wed, 3 Jan 2024 05:58:59 -0800 Subject: [PATCH 057/361] Remove tile pointer/ripple/index when it has no action (#19137) * Remove tile pointer/ripple/index when it has no action * update * Apply suggestions from code review Co-authored-by: Paul Bottein --------- Co-authored-by: Paul Bottein --- src/panels/lovelace/cards/hui-tile-card.ts | 27 ++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts index 1c06426d1acb..b3470aeed569 100644 --- a/src/panels/lovelace/cards/hui-tile-card.ts +++ b/src/panels/lovelace/cards/hui-tile-card.ts @@ -287,21 +287,40 @@ export class HuiTileCard extends LitElement implements LovelaceCard { @eventOptions({ passive: true }) private handleRippleActivate(evt?: Event) { + if (!this.hasCardAction) return; this._rippleHandlers.startPress(evt); } private handleRippleDeactivate() { + if (!this.hasCardAction) return; this._rippleHandlers.endPress(); } private handleRippleMouseEnter() { + if (!this.hasCardAction) return; this._rippleHandlers.startHover(); } private handleRippleMouseLeave() { + if (!this.hasCardAction) return; this._rippleHandlers.endHover(); } + get hasCardAction() { + return ( + !this._config?.tap_action || + hasAction(this._config?.tap_action) || + hasAction(this._config?.hold_action) || + hasAction(this._config?.double_tap_action) + ); + } + + get hasIconAction() { + return ( + !this._config?.icon_tap_action || hasAction(this._config?.icon_tap_action) + ); + } + protected render() { if (!this._config || !this.hass) { return nothing; @@ -368,8 +387,8 @@ export class HuiTileCard extends LitElement implements LovelaceCard { hasHold: hasAction(this._config!.hold_action), hasDoubleClick: hasAction(this._config!.double_tap_action), })} - role="button" - tabindex="0" + role=${ifDefined(this.hasCardAction ? "button" : undefined)} + tabindex=${ifDefined(this.hasCardAction ? "0" : undefined)} aria-labelledby="info" @mousedown=${this.handleRippleActivate} @mouseup=${this.handleRippleDeactivate} @@ -386,8 +405,8 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
From 6929a9c6037b987a1ede770625ad4ef290b47fb2 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 14:59:45 +0100 Subject: [PATCH 058/361] Bumped version to 20240103.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 570bc96eaf74..f43e4cf0dc55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240103.1" +version = "20240103.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From ae0eac3415f9df2cbab002c1f09742f0ee70c573 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 14:59:45 +0100 Subject: [PATCH 059/361] Bumped version to 20240103.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 570bc96eaf74..f43e4cf0dc55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240103.1" +version = "20240103.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From 22929672a069db25a0a94f230c8c9f57ac0afdd7 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Wed, 3 Jan 2024 05:58:59 -0800 Subject: [PATCH 060/361] Remove tile pointer/ripple/index when it has no action (#19137) * Remove tile pointer/ripple/index when it has no action * update * Apply suggestions from code review Co-authored-by: Paul Bottein --------- Co-authored-by: Paul Bottein --- src/panels/lovelace/cards/hui-tile-card.ts | 27 ++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts index 1c06426d1acb..b3470aeed569 100644 --- a/src/panels/lovelace/cards/hui-tile-card.ts +++ b/src/panels/lovelace/cards/hui-tile-card.ts @@ -287,21 +287,40 @@ export class HuiTileCard extends LitElement implements LovelaceCard { @eventOptions({ passive: true }) private handleRippleActivate(evt?: Event) { + if (!this.hasCardAction) return; this._rippleHandlers.startPress(evt); } private handleRippleDeactivate() { + if (!this.hasCardAction) return; this._rippleHandlers.endPress(); } private handleRippleMouseEnter() { + if (!this.hasCardAction) return; this._rippleHandlers.startHover(); } private handleRippleMouseLeave() { + if (!this.hasCardAction) return; this._rippleHandlers.endHover(); } + get hasCardAction() { + return ( + !this._config?.tap_action || + hasAction(this._config?.tap_action) || + hasAction(this._config?.hold_action) || + hasAction(this._config?.double_tap_action) + ); + } + + get hasIconAction() { + return ( + !this._config?.icon_tap_action || hasAction(this._config?.icon_tap_action) + ); + } + protected render() { if (!this._config || !this.hass) { return nothing; @@ -368,8 +387,8 @@ export class HuiTileCard extends LitElement implements LovelaceCard { hasHold: hasAction(this._config!.hold_action), hasDoubleClick: hasAction(this._config!.double_tap_action), })} - role="button" - tabindex="0" + role=${ifDefined(this.hasCardAction ? "button" : undefined)} + tabindex=${ifDefined(this.hasCardAction ? "0" : undefined)} aria-labelledby="info" @mousedown=${this.handleRippleActivate} @mouseup=${this.handleRippleDeactivate} @@ -386,8 +405,8 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
From 62dafac72b2c4fcc3975122aaa2c390dc1abcc80 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 3 Jan 2024 14:26:40 +0100 Subject: [PATCH 061/361] Display edit button for climate fan mode feature (#19259) --- .../lovelace/editor/config-elements/hui-card-features-editor.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts b/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts index 49290ba57102..8693be890d8d 100644 --- a/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts @@ -81,6 +81,7 @@ const EDITABLES_FEATURE_TYPES = new Set([ "humidifier-modes", "water-heater-operation-modes", "lawn-mower-commands", + "climate-fan-modes", "climate-preset-modes", "numeric-input", "update-actions", From 2c69fe8c53cca9b1d3a1cda718b16cb06f8d23d4 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 14:58:36 +0100 Subject: [PATCH 062/361] Fix checking todo item that dont support due date (#19262) * Fix checking todo item that dont support due date * make cleaner * Revert "make cleaner" This reverts commit fa33b3361451dd334d9f69142f9754a1ea2c1ca4. * Update dialog-todo-item-editor.ts * do check in 1 place --- src/data/todo.ts | 12 +++++++++--- src/panels/lovelace/cards/hui-todo-list-card.ts | 3 ++- src/panels/todo/dialog-todo-item-editor.ts | 12 +++++++++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/data/todo.ts b/src/data/todo.ts index 9af8ef0f4cc6..659c8d0c3c24 100644 --- a/src/data/todo.ts +++ b/src/data/todo.ts @@ -83,9 +83,12 @@ export const updateItem = ( item: item.uid, rename: item.summary, status: item.status, - description: item.description || null, + description: item.description, due_datetime: item.due?.includes("T") ? item.due : undefined, - due_date: item.due?.includes("T") ? undefined : item.due || null, + due_date: + item.due === undefined || item.due?.includes("T") + ? undefined + : item.due, }, { entity_id } ); @@ -102,7 +105,10 @@ export const createItem = ( item: item.summary, description: item.description || undefined, due_datetime: item.due?.includes("T") ? item.due : undefined, - due_date: item.due?.includes("T") ? undefined : item.due, + due_date: + item.due === undefined || item.due?.includes("T") + ? undefined + : item.due, }, { entity_id } ); diff --git a/src/panels/lovelace/cards/hui-todo-list-card.ts b/src/panels/lovelace/cards/hui-todo-list-card.ts index 3352f7a42b43..d1d62880f8ed 100644 --- a/src/panels/lovelace/cards/hui-todo-list-card.ts +++ b/src/panels/lovelace/cards/hui-todo-list-card.ts @@ -476,7 +476,8 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard { return; } await updateItem(this.hass!, this._entityId!, { - ...item, + uid: item.uid, + summary: item.summary, status: item.status === TodoItemStatus.NeedsAction ? TodoItemStatus.Completed diff --git a/src/panels/todo/dialog-todo-item-editor.ts b/src/panels/todo/dialog-todo-item-editor.ts index cd26ad35fc28..daa5eff68627 100644 --- a/src/panels/todo/dialog-todo-item-editor.ts +++ b/src/panels/todo/dialog-todo-item-editor.ts @@ -324,14 +324,20 @@ class DialogTodoItemEditor extends LitElement { (this._todoListSupportsFeature( TodoListEntityFeature.SET_DESCRIPTION_ON_ITEM ) - ? // backend should accept null to clear the field, but it doesn't now - null + ? null : undefined), due: this._due ? this._hasTime ? this._due.toISOString() : this._formatDate(this._due) - : null, + : this._todoListSupportsFeature( + TodoListEntityFeature.SET_DUE_DATETIME_ON_ITEM + ) || + this._todoListSupportsFeature( + TodoListEntityFeature.SET_DUE_DATE_ON_ITEM + ) + ? null + : undefined, status: this._checked ? TodoItemStatus.Completed : TodoItemStatus.NeedsAction, From 288d173a4d2fcf4ec665e4fffee4015550dafa67 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 15:02:14 +0100 Subject: [PATCH 063/361] Bumped version to 20240103.3 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f43e4cf0dc55..b1f2ee8ea705 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240103.0" +version = "20240103.3" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From 7a6fc573c206d096ef61b8fe59e9170d5b52daaf Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 15:19:30 +0100 Subject: [PATCH 064/361] Fix version bump script (#19264) --- script/{version_bump.cjs => version_bump.js} | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) rename script/{version_bump.cjs => version_bump.js} (83%) diff --git a/script/version_bump.cjs b/script/version_bump.js similarity index 83% rename from script/version_bump.cjs rename to script/version_bump.js index a1c8f9c9be6f..fbba50b6a7ab 100755 --- a/script/version_bump.cjs +++ b/script/version_bump.js @@ -1,7 +1,10 @@ #!/usr/bin/env node -const fs = require("fs"); -const util = require("util"); -const exec = util.promisify(require("child_process").exec); +/* eslint-disable no-console */ +import fs from "fs"; +import util from "util"; +import child_process from "child_process"; + +const exec = util.promisify(child_process.exec); function patch(version) { const parts = version.split("."); @@ -18,7 +21,7 @@ function today() { function auto(version) { const todayVersion = today(); - if (todayVersion !== version) { + if (todayVersion.split(".")[0] !== version.split(".")[0]) { return todayVersion; } return patch(version); @@ -44,7 +47,7 @@ async function main(args) { commit = true; } else { method = args.length > 0 && methods[args[0]]; - commit = args.length > 1 && args[1] == "--commit"; + commit = args.length > 1 && args[1] === "--commit"; } if (!method) { From 979085a9defd27e6b8936aa6be2d0d45843921df Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 3 Jan 2024 20:35:54 +0100 Subject: [PATCH 065/361] Fix supervisor dev build (#19266) --- build-scripts/gulp/translations.js | 1 + 1 file changed, 1 insertion(+) diff --git a/build-scripts/gulp/translations.js b/build-scripts/gulp/translations.js index 967da71efdfc..fd4cccc013a8 100755 --- a/build-scripts/gulp/translations.js +++ b/build-scripts/gulp/translations.js @@ -426,6 +426,7 @@ gulp.task( "fetch-nightly-translations", gulp.series("clean-translations", "ensure-translations-build-dir") ), + gulp.parallel("create-test-metadata", "create-test-translation"), "build-master-translation", "build-merged-translations", "build-translation-fragment-supervisor", From 3984702d3eba9fde82c405fcea2a60cedc75a961 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Wed, 3 Jan 2024 11:36:59 -0800 Subject: [PATCH 066/361] Fix select view dialog (#19267) * Fix select view dialog * add import --- .../select-view/hui-dialog-select-view.ts | 21 ++++++++++++++----- src/translations/en.json | 4 +++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/panels/lovelace/editor/select-view/hui-dialog-select-view.ts b/src/panels/lovelace/editor/select-view/hui-dialog-select-view.ts index 6a9c8eb04fdc..5f3e073f3a4f 100644 --- a/src/panels/lovelace/editor/select-view/hui-dialog-select-view.ts +++ b/src/panels/lovelace/editor/select-view/hui-dialog-select-view.ts @@ -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 { })} ` : ""} - ${this._config - ? this._config.views.length > 1 + ${!this._config || (this._config.views || []).length < 1 + ? html`${this.hass.localize( + this._config + ? "ui.panel.lovelace.editor.select_view.no_views" + : "ui.panel.lovelace.editor.select_view.no_config" + )}` + : this._config.views.length > 1 ? html` ${this._config.views.map( @@ -125,8 +133,7 @@ export class HuiDialogSelectView extends LitElement { )} ` - : "" - : html`
No config found.
`} + : ""} ${this.hass!.localize("ui.common.cancel")} - + ${this._params.actionLabel || this.hass!.localize("ui.common.move")} diff --git a/src/translations/en.json b/src/translations/en.json index 53306cd8b77d..74467bcbf1ab 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -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", From 0d8c0ac1a0c84cee9d1e14f1bc306b8424294c7d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 17:45:46 -0500 Subject: [PATCH 067/361] Update dependency marked to v11.1.1 (#19254) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 663a412014d2..8f2a790e78e0 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/yarn.lock b/yarn.lock index 2f9b96e6b6ef..59d16bf0e735 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9676,7 +9676,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" @@ -11652,12 +11652,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 From 4f05bd9e22f8cd91f288e4af88ddcb5dd8ab6c15 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 4 Jan 2024 03:21:42 +0100 Subject: [PATCH 068/361] Fix circular progress size + fix bug in assist pipeline debug (#19268) --- src/auth/ha-auth-textfield.ts | 2 +- src/components/media-player/ha-media-upload-button.ts | 2 +- src/panels/config/repairs/dialog-system-information.ts | 2 +- .../voice-assistants/debug/assist-pipeline-run-debug.ts | 7 +++++-- .../voice-assistants/debug/assist-render-pipeline-run.ts | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/auth/ha-auth-textfield.ts b/src/auth/ha-auth-textfield.ts index 123deef03fe9..20d5e66174c8 100644 --- a/src/auth/ha-auth-textfield.ts +++ b/src/auth/ha-auth-textfield.ts @@ -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` 0 ? html` `; } else if (info.type === "failed") { diff --git a/src/panels/config/voice-assistants/debug/assist-pipeline-run-debug.ts b/src/panels/config/voice-assistants/debug/assist-pipeline-run-debug.ts index 67b902ba6581..f7df3507fa4e 100644 --- a/src/panels/config/voice-assistants/debug/assist-pipeline-run-debug.ts +++ b/src/panels/config/voice-assistants/debug/assist-pipeline-run-debug.ts @@ -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; } }, diff --git a/src/panels/config/voice-assistants/debug/assist-render-pipeline-run.ts b/src/panels/config/voice-assistants/debug/assist-render-pipeline-run.ts index 05da128692af..ae455152beb0 100644 --- a/src/panels/config/voice-assistants/debug/assist-render-pipeline-run.ts +++ b/src/panels/config/voice-assistants/debug/assist-render-pipeline-run.ts @@ -90,7 +90,7 @@ const renderProgress = ( return html`❌`; } return html` - + `; } From e427ffca5fc136d5c16a4503a6fe8b68ac449606 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 4 Jan 2024 03:27:30 +0100 Subject: [PATCH 069/361] Fix turning valve on/off (#19269) --- src/common/const.ts | 1 + src/panels/lovelace/common/entity/turn-on-off-entity.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/common/const.ts b/src/common/const.ts index 68f4fa97b1c1..bc114f2f1703 100644 --- a/src/common/const.ts +++ b/src/common/const.ts @@ -272,6 +272,7 @@ export const DOMAINS_TOGGLE = new Set([ "group", "automation", "humidifier", + "valve", ]); /** Domains that have a dynamic entity image / picture. */ diff --git a/src/panels/lovelace/common/entity/turn-on-off-entity.ts b/src/panels/lovelace/common/entity/turn-on-off-entity.ts index 701c2c4996ab..5be6beaea844 100644 --- a/src/panels/lovelace/common/entity/turn-on-off-entity.ts +++ b/src/panels/lovelace/common/entity/turn-on-off-entity.ts @@ -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"; } From e5d31d85dd91c1387fbddd5b8ad2a0fbfeef04d0 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Thu, 4 Jan 2024 10:54:20 +0100 Subject: [PATCH 070/361] Update getStates to support valves (#19277) --- src/common/entity/get_states.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/entity/get_states.ts b/src/common/entity/get_states.ts index 29c11ca48c42..456ce27bcea5 100644 --- a/src/common/entity/get_states.ts +++ b/src/common/entity/get_states.ts @@ -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", From ecadc06b452c180d97c8fa9d8f776fb3a690712f Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 4 Jan 2024 11:52:38 +0100 Subject: [PATCH 071/361] fix valve entities row (#19278) --- src/common/const.ts | 1 + src/data/valve.ts | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/common/const.ts b/src/common/const.ts index bc114f2f1703..2e7d2f7c77d7 100644 --- a/src/common/const.ts +++ b/src/common/const.ts @@ -254,6 +254,7 @@ export const DOMAINS_INPUT_ROW = [ "text", "time", "vacuum", + "valve", ]; /** States that we consider "off". */ diff --git a/src/data/valve.ts b/src/data/valve.ts index 73f5d428ae18..645ca82e4954 100644 --- a/src/data/valve.ts +++ b/src/data/valve.ts @@ -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"; From fd6cae48b7e2940356589881d4b0d0f3f34b0a31 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 4 Jan 2024 13:20:35 +0100 Subject: [PATCH 072/361] Remove overflow hidden from profile (#19279) --- src/panels/profile/ha-panel-profile.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/panels/profile/ha-panel-profile.ts b/src/panels/profile/ha-panel-profile.ts index 1756af4d9333..9e82e842df5f 100644 --- a/src/panels/profile/ha-panel-profile.ts +++ b/src/panels/profile/ha-panel-profile.ts @@ -250,7 +250,6 @@ class HaPanelProfile extends LitElement { max-width: 600px; margin: 0 auto; padding-bottom: env(safe-area-inset-bottom); - overflow: hidden; } .content > * { From 8615b799c6ede94aabca3a8a0ae54d8fdbf5b8fe Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 4 Jan 2024 14:24:33 +0100 Subject: [PATCH 073/361] Fix due date when no time in certain timezones (#19280) * Fix due date when no time in certain timezones * Update dialog-todo-item-editor.ts --- src/panels/lovelace/cards/hui-todo-list-card.ts | 2 +- src/panels/todo/dialog-todo-item-editor.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/panels/lovelace/cards/hui-todo-list-card.ts b/src/panels/lovelace/cards/hui-todo-list-card.ts index d1d62880f8ed..1d1c6b6c8243 100644 --- a/src/panels/lovelace/cards/hui-todo-list-card.ts +++ b/src/panels/lovelace/cards/hui-todo-list-card.ts @@ -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); diff --git a/src/panels/todo/dialog-todo-item-editor.ts b/src/panels/todo/dialog-todo-item-editor.ts index daa5eff68627..be03e260eccf 100644 --- a/src/panels/todo/dialog-todo-item-editor.ts +++ b/src/panels/todo/dialog-todo-item-editor.ts @@ -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; From 72dedc7596a0626f858848afebf71ed77cf21ddd Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Thu, 4 Jan 2024 16:18:16 +0100 Subject: [PATCH 074/361] Fix thermostat and humidifier card rendering when off (#19281) * Fix thermostat and humidifier card rendering when off * Fix action color --- .../ha-state-control-climate-temperature.ts | 43 +++++++++++++------ .../ha-state-control-humidifier-humidity.ts | 37 ++++++++++++---- .../state-control-circular-slider-style.ts | 13 +++++- 3 files changed, 71 insertions(+), 22 deletions(-) diff --git a/src/state-control/climate/ha-state-control-climate-temperature.ts b/src/state-control/climate/ha-state-control-climate-temperature.ts index 7634fd2f2d18..0264af5ec7b3 100644 --- a/src/state-control/climate/ha-state-control-climate-temperature.ts +++ b/src/state-control/climate/ha-state-control-climate-temperature.ts @@ -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`

- ${action + ${action && action !== "off" ? this.hass.formatEntityAttributeValue(this.stateObj, "hvac_action") - : this.hass.formatEntityState(this.stateObj)} + : isTemperatureDisplayed + ? this.hass.formatEntityState(this.stateObj) + : nothing}

`; } @@ -315,6 +324,14 @@ export class HaStateControlClimateTemperature extends LitElement { `; } + if (this.stateObj.state !== UNAVAILABLE) { + return html` +

+ ${this.hass.formatEntityState(this.stateObj)} +

+ `; + } + return nothing; } @@ -373,6 +390,14 @@ export class HaStateControlClimateTemperature extends LitElement { return html`

`; } + private _renderInfo() { + return html` +
+ ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()} +
+ `; + } + get _supportsTargetTemperature() { return ( supportsFeature(this.stateObj, ClimateEntityFeature.TARGET_TEMPERATURE) && @@ -447,10 +472,7 @@ export class HaStateControlClimateTemperature extends LitElement { @value-changing=${this._valueChanging} > -
- ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()} -
- ${this._renderTemperatureButtons("value")} + ${this._renderInfo()} ${this._renderTemperatureButtons("value")}
`; } @@ -484,9 +506,7 @@ export class HaStateControlClimateTemperature extends LitElement { @high-changing=${this._valueChanging} > -
- ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()} -
+ ${this._renderInfo()} ${this._renderTemperatureButtons(this._selectTargetTemperature, true)}
`; @@ -497,6 +517,7 @@ export class HaStateControlClimateTemperature extends LitElement { class="container${containerSizeClass}" style=${styleMap({ "--state-color": stateColor, + "--action-color": actionColor, })} > -
- ${this._renderLabel()} ${this._renderSecondary()} -
+ ${this._renderInfo()}
`; } diff --git a/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts b/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts index 6078180cd849..459e8d611730 100644 --- a/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts +++ b/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts @@ -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`

- ${action + ${action && action !== "off" ? this.hass.formatEntityAttributeValue(this.stateObj, "action") - : this.hass.formatEntityState(this.stateObj)} + : isHumidityDisplayed + ? this.hass.formatEntityState(this.stateObj) + : nothing}

`; } @@ -144,6 +151,14 @@ export class HaStateControlHumidifierHumidity extends LitElement { return this._renderTarget(this._targetHumidity!, "big"); } + if (this.stateObj.state !== UNAVAILABLE) { + return html` +

+ ${this.hass.formatEntityState(this.stateObj)} +

+ `; + } + return nothing; } @@ -225,6 +240,14 @@ export class HaStateControlHumidifierHumidity extends LitElement { `; } + private _renderInfo() { + return html` +
+ ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()} +
+ `; + } + 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} > -
- ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()} -
- ${this._renderButtons()} + ${this._renderInfo()} ${this._renderButtons()}
`; } @@ -284,6 +304,7 @@ export class HaStateControlHumidifierHumidity extends LitElement {
@@ -296,9 +317,7 @@ export class HaStateControlHumidifierHumidity extends LitElement { disabled > -
- ${this._renderLabel()} ${this._renderSecondary()} -
+ ${this._renderInfo()}
`; } diff --git a/src/state-control/state-control-circular-slider-style.ts b/src/state-control/state-control-circular-slider-style.ts index cc1c9366d7e9..b5d4d5281a03 100644 --- a/src/state-control/state-control-circular-slider-style.ts +++ b/src/state-control/state-control-circular-slider-style.ts @@ -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; } From fe5431976d5c8c4a77e525f60a95ddbebb907baf Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 4 Jan 2024 17:43:37 +0100 Subject: [PATCH 075/361] Bumped version to 20240104.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f43e4cf0dc55..d9414825fabf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240103.0" +version = "20240104.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From fef2c44cb8ffe4ff3b0827365da3ba068e193ad3 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 4 Jan 2024 17:43:37 +0100 Subject: [PATCH 076/361] Bumped version to 20240104.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b1f2ee8ea705..d9414825fabf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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" From 030566c1e849997c3ec39ec82c6b86ac9c2048fc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 17:45:46 -0500 Subject: [PATCH 077/361] Update dependency marked to v11.1.1 (#19254) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 3f4e61c24329..0d2a855179f1 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/yarn.lock b/yarn.lock index 510c103b2e84..3997cc2fa300 100644 --- a/yarn.lock +++ b/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 From 0b20725f5f42824d67168714f50632fd11e013bc Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Wed, 3 Jan 2024 11:36:59 -0800 Subject: [PATCH 078/361] Fix select view dialog (#19267) * Fix select view dialog * add import --- .../select-view/hui-dialog-select-view.ts | 21 ++++++++++++++----- src/translations/en.json | 4 +++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/panels/lovelace/editor/select-view/hui-dialog-select-view.ts b/src/panels/lovelace/editor/select-view/hui-dialog-select-view.ts index 6a9c8eb04fdc..5f3e073f3a4f 100644 --- a/src/panels/lovelace/editor/select-view/hui-dialog-select-view.ts +++ b/src/panels/lovelace/editor/select-view/hui-dialog-select-view.ts @@ -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 { })} ` : ""} - ${this._config - ? this._config.views.length > 1 + ${!this._config || (this._config.views || []).length < 1 + ? html`${this.hass.localize( + this._config + ? "ui.panel.lovelace.editor.select_view.no_views" + : "ui.panel.lovelace.editor.select_view.no_config" + )}` + : this._config.views.length > 1 ? html` ${this._config.views.map( @@ -125,8 +133,7 @@ export class HuiDialogSelectView extends LitElement { )} ` - : "" - : html`
No config found.
`} + : ""} ${this.hass!.localize("ui.common.cancel")} - + ${this._params.actionLabel || this.hass!.localize("ui.common.move")} diff --git a/src/translations/en.json b/src/translations/en.json index 53306cd8b77d..74467bcbf1ab 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -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", From efddbfcfa0941eccce4565a30c12dd689c7d6624 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 4 Jan 2024 03:21:42 +0100 Subject: [PATCH 079/361] Fix circular progress size + fix bug in assist pipeline debug (#19268) --- src/auth/ha-auth-textfield.ts | 2 +- src/components/media-player/ha-media-upload-button.ts | 2 +- src/panels/config/repairs/dialog-system-information.ts | 2 +- .../voice-assistants/debug/assist-pipeline-run-debug.ts | 7 +++++-- .../voice-assistants/debug/assist-render-pipeline-run.ts | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/auth/ha-auth-textfield.ts b/src/auth/ha-auth-textfield.ts index 123deef03fe9..20d5e66174c8 100644 --- a/src/auth/ha-auth-textfield.ts +++ b/src/auth/ha-auth-textfield.ts @@ -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` 0 ? html` `; } else if (info.type === "failed") { diff --git a/src/panels/config/voice-assistants/debug/assist-pipeline-run-debug.ts b/src/panels/config/voice-assistants/debug/assist-pipeline-run-debug.ts index 67b902ba6581..f7df3507fa4e 100644 --- a/src/panels/config/voice-assistants/debug/assist-pipeline-run-debug.ts +++ b/src/panels/config/voice-assistants/debug/assist-pipeline-run-debug.ts @@ -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; } }, diff --git a/src/panels/config/voice-assistants/debug/assist-render-pipeline-run.ts b/src/panels/config/voice-assistants/debug/assist-render-pipeline-run.ts index 05da128692af..ae455152beb0 100644 --- a/src/panels/config/voice-assistants/debug/assist-render-pipeline-run.ts +++ b/src/panels/config/voice-assistants/debug/assist-render-pipeline-run.ts @@ -90,7 +90,7 @@ const renderProgress = ( return html`❌`; } return html` - + `; } From 32fd8270d77ce80be6944d40807bcf6a6dcf1a07 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 4 Jan 2024 03:27:30 +0100 Subject: [PATCH 080/361] Fix turning valve on/off (#19269) --- src/common/const.ts | 1 + src/panels/lovelace/common/entity/turn-on-off-entity.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/common/const.ts b/src/common/const.ts index 68f4fa97b1c1..bc114f2f1703 100644 --- a/src/common/const.ts +++ b/src/common/const.ts @@ -272,6 +272,7 @@ export const DOMAINS_TOGGLE = new Set([ "group", "automation", "humidifier", + "valve", ]); /** Domains that have a dynamic entity image / picture. */ diff --git a/src/panels/lovelace/common/entity/turn-on-off-entity.ts b/src/panels/lovelace/common/entity/turn-on-off-entity.ts index 701c2c4996ab..5be6beaea844 100644 --- a/src/panels/lovelace/common/entity/turn-on-off-entity.ts +++ b/src/panels/lovelace/common/entity/turn-on-off-entity.ts @@ -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"; } From 8d541595b80638dc9ff5f4762bb243a8d77cce87 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Thu, 4 Jan 2024 10:54:20 +0100 Subject: [PATCH 081/361] Update getStates to support valves (#19277) --- src/common/entity/get_states.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/entity/get_states.ts b/src/common/entity/get_states.ts index 29c11ca48c42..456ce27bcea5 100644 --- a/src/common/entity/get_states.ts +++ b/src/common/entity/get_states.ts @@ -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", From f147a5e909bc94e6bc1ed5364d9ac8791e2002a2 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 4 Jan 2024 11:52:38 +0100 Subject: [PATCH 082/361] fix valve entities row (#19278) --- src/common/const.ts | 1 + src/data/valve.ts | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/common/const.ts b/src/common/const.ts index bc114f2f1703..2e7d2f7c77d7 100644 --- a/src/common/const.ts +++ b/src/common/const.ts @@ -254,6 +254,7 @@ export const DOMAINS_INPUT_ROW = [ "text", "time", "vacuum", + "valve", ]; /** States that we consider "off". */ diff --git a/src/data/valve.ts b/src/data/valve.ts index 73f5d428ae18..645ca82e4954 100644 --- a/src/data/valve.ts +++ b/src/data/valve.ts @@ -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"; From a1cf18468b2bafade0bbb4f4e0552bdc1fd955b3 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 4 Jan 2024 13:20:35 +0100 Subject: [PATCH 083/361] Remove overflow hidden from profile (#19279) --- src/panels/profile/ha-panel-profile.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/panels/profile/ha-panel-profile.ts b/src/panels/profile/ha-panel-profile.ts index 1756af4d9333..9e82e842df5f 100644 --- a/src/panels/profile/ha-panel-profile.ts +++ b/src/panels/profile/ha-panel-profile.ts @@ -250,7 +250,6 @@ class HaPanelProfile extends LitElement { max-width: 600px; margin: 0 auto; padding-bottom: env(safe-area-inset-bottom); - overflow: hidden; } .content > * { From a31b9f1b4d952353a3f61b5905fdf6ee1eeec8ef Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 4 Jan 2024 14:24:33 +0100 Subject: [PATCH 084/361] Fix due date when no time in certain timezones (#19280) * Fix due date when no time in certain timezones * Update dialog-todo-item-editor.ts --- src/panels/lovelace/cards/hui-todo-list-card.ts | 2 +- src/panels/todo/dialog-todo-item-editor.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/panels/lovelace/cards/hui-todo-list-card.ts b/src/panels/lovelace/cards/hui-todo-list-card.ts index d1d62880f8ed..1d1c6b6c8243 100644 --- a/src/panels/lovelace/cards/hui-todo-list-card.ts +++ b/src/panels/lovelace/cards/hui-todo-list-card.ts @@ -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); diff --git a/src/panels/todo/dialog-todo-item-editor.ts b/src/panels/todo/dialog-todo-item-editor.ts index daa5eff68627..be03e260eccf 100644 --- a/src/panels/todo/dialog-todo-item-editor.ts +++ b/src/panels/todo/dialog-todo-item-editor.ts @@ -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; From 456c011f3edc0e31e3c49434dfaf37f3f715d485 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Thu, 4 Jan 2024 16:18:16 +0100 Subject: [PATCH 085/361] Fix thermostat and humidifier card rendering when off (#19281) * Fix thermostat and humidifier card rendering when off * Fix action color --- .../ha-state-control-climate-temperature.ts | 43 +++++++++++++------ .../ha-state-control-humidifier-humidity.ts | 37 ++++++++++++---- .../state-control-circular-slider-style.ts | 13 +++++- 3 files changed, 71 insertions(+), 22 deletions(-) diff --git a/src/state-control/climate/ha-state-control-climate-temperature.ts b/src/state-control/climate/ha-state-control-climate-temperature.ts index 7634fd2f2d18..0264af5ec7b3 100644 --- a/src/state-control/climate/ha-state-control-climate-temperature.ts +++ b/src/state-control/climate/ha-state-control-climate-temperature.ts @@ -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`

- ${action + ${action && action !== "off" ? this.hass.formatEntityAttributeValue(this.stateObj, "hvac_action") - : this.hass.formatEntityState(this.stateObj)} + : isTemperatureDisplayed + ? this.hass.formatEntityState(this.stateObj) + : nothing}

`; } @@ -315,6 +324,14 @@ export class HaStateControlClimateTemperature extends LitElement { `; } + if (this.stateObj.state !== UNAVAILABLE) { + return html` +

+ ${this.hass.formatEntityState(this.stateObj)} +

+ `; + } + return nothing; } @@ -373,6 +390,14 @@ export class HaStateControlClimateTemperature extends LitElement { return html`

`; } + private _renderInfo() { + return html` +
+ ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()} +
+ `; + } + get _supportsTargetTemperature() { return ( supportsFeature(this.stateObj, ClimateEntityFeature.TARGET_TEMPERATURE) && @@ -447,10 +472,7 @@ export class HaStateControlClimateTemperature extends LitElement { @value-changing=${this._valueChanging} > -
- ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()} -
- ${this._renderTemperatureButtons("value")} + ${this._renderInfo()} ${this._renderTemperatureButtons("value")}
`; } @@ -484,9 +506,7 @@ export class HaStateControlClimateTemperature extends LitElement { @high-changing=${this._valueChanging} > -
- ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()} -
+ ${this._renderInfo()} ${this._renderTemperatureButtons(this._selectTargetTemperature, true)}
`; @@ -497,6 +517,7 @@ export class HaStateControlClimateTemperature extends LitElement { class="container${containerSizeClass}" style=${styleMap({ "--state-color": stateColor, + "--action-color": actionColor, })} > -
- ${this._renderLabel()} ${this._renderSecondary()} -
+ ${this._renderInfo()}
`; } diff --git a/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts b/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts index 6078180cd849..459e8d611730 100644 --- a/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts +++ b/src/state-control/humidifier/ha-state-control-humidifier-humidity.ts @@ -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`

- ${action + ${action && action !== "off" ? this.hass.formatEntityAttributeValue(this.stateObj, "action") - : this.hass.formatEntityState(this.stateObj)} + : isHumidityDisplayed + ? this.hass.formatEntityState(this.stateObj) + : nothing}

`; } @@ -144,6 +151,14 @@ export class HaStateControlHumidifierHumidity extends LitElement { return this._renderTarget(this._targetHumidity!, "big"); } + if (this.stateObj.state !== UNAVAILABLE) { + return html` +

+ ${this.hass.formatEntityState(this.stateObj)} +

+ `; + } + return nothing; } @@ -225,6 +240,14 @@ export class HaStateControlHumidifierHumidity extends LitElement { `; } + private _renderInfo() { + return html` +
+ ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()} +
+ `; + } + 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} > -
- ${this._renderLabel()}${this._renderPrimary()}${this._renderSecondary()} -
- ${this._renderButtons()} + ${this._renderInfo()} ${this._renderButtons()}
`; } @@ -284,6 +304,7 @@ export class HaStateControlHumidifierHumidity extends LitElement {
@@ -296,9 +317,7 @@ export class HaStateControlHumidifierHumidity extends LitElement { disabled > -
- ${this._renderLabel()} ${this._renderSecondary()} -
+ ${this._renderInfo()}
`; } diff --git a/src/state-control/state-control-circular-slider-style.ts b/src/state-control/state-control-circular-slider-style.ts index cc1c9366d7e9..b5d4d5281a03 100644 --- a/src/state-control/state-control-circular-slider-style.ts +++ b/src/state-control/state-control-circular-slider-style.ts @@ -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; } From 249c89669e67d420918609df807aa5aa47d5b2cb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 13:11:06 -0500 Subject: [PATCH 086/361] Update dependency systemjs to v6.14.3 (#19282) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 8f2a790e78e0..c512c677b083 100644 --- a/package.json +++ b/package.json @@ -233,7 +233,7 @@ "serve-handler": "6.1.5", "sinon": "17.0.1", "source-map-url": "0.4.1", - "systemjs": "6.14.2", + "systemjs": "6.14.3", "tar": "6.2.0", "terser-webpack-plugin": "5.3.10", "ts-lit-plugin": "2.0.1", diff --git a/yarn.lock b/yarn.lock index 59d16bf0e735..7f38d4b8e0d3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9700,7 +9700,7 @@ __metadata: source-map-url: "npm:0.4.1" stacktrace-js: "npm:2.0.2" superstruct: "npm:1.0.3" - systemjs: "npm:6.14.2" + systemjs: "npm:6.14.3" tar: "npm:6.2.0" terser-webpack-plugin: "npm:5.3.10" tinykeys: "npm:2.1.0" @@ -14931,10 +14931,10 @@ __metadata: languageName: node linkType: hard -"systemjs@npm:6.14.2": - version: 6.14.2 - resolution: "systemjs@npm:6.14.2" - checksum: 5e126987ab10c3a19c3134d1ca82ab18cbf05018b396b0cc64c31c9cd561e5129f134cd0985d1987d7f82bd115a9b03182658ea76d612c58e8acfd446cda550f +"systemjs@npm:6.14.3": + version: 6.14.3 + resolution: "systemjs@npm:6.14.3" + checksum: 5d79c3b7dbd68b246fba6a9fe2372b88765c61cb1dbbd550beaaae0a4b38a1f19de302e203f2106845f959d00c1e7f9976bccf9b0527e907d5f3d8b5c6c5f61a languageName: node linkType: hard From 554e5b7be55f2898fd3a251a9a657a2da30d780b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 19:48:57 -0500 Subject: [PATCH 087/361] Update typescript-eslint monorepo to v6.17.0 (#19286) --- package.json | 4 +- yarn.lock | 104 +++++++++++++++++++++++++-------------------------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/package.json b/package.json index c512c677b083..492548711772 100644 --- a/package.json +++ b/package.json @@ -184,8 +184,8 @@ "@types/tar": "6.1.10", "@types/ua-parser-js": "0.7.39", "@types/webspeechapi": "0.0.29", - "@typescript-eslint/eslint-plugin": "6.16.0", - "@typescript-eslint/parser": "6.16.0", + "@typescript-eslint/eslint-plugin": "6.17.0", + "@typescript-eslint/parser": "6.17.0", "@web/dev-server": "0.1.38", "@web/dev-server-rollup": "0.4.1", "babel-loader": "9.1.3", diff --git a/yarn.lock b/yarn.lock index 7f38d4b8e0d3..d96a28098a86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4563,15 +4563,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:6.16.0": - version: 6.16.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.16.0" +"@typescript-eslint/eslint-plugin@npm:6.17.0": + version: 6.17.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.17.0" dependencies: "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:6.16.0" - "@typescript-eslint/type-utils": "npm:6.16.0" - "@typescript-eslint/utils": "npm:6.16.0" - "@typescript-eslint/visitor-keys": "npm:6.16.0" + "@typescript-eslint/scope-manager": "npm:6.17.0" + "@typescript-eslint/type-utils": "npm:6.17.0" + "@typescript-eslint/utils": "npm:6.17.0" + "@typescript-eslint/visitor-keys": "npm:6.17.0" debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" ignore: "npm:^5.2.4" @@ -4584,44 +4584,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 4bedce948ac3c20492a59813ee5d4f1f2306310857864dfaac2736f6c38e18785002c36844fd64c9fbdf3059fc390b29412be105fd7a118177f1eeeb1eb533f7 + checksum: f2a5774e9cc03e491a5a488501e5622c7eebd766f5a4fc2c30642864a3b89b0807946bde33a678f326ba7032f3f6a51aa0bf9c2d10adc823804fc9fb47db55a6 languageName: node linkType: hard -"@typescript-eslint/parser@npm:6.16.0": - version: 6.16.0 - resolution: "@typescript-eslint/parser@npm:6.16.0" +"@typescript-eslint/parser@npm:6.17.0": + version: 6.17.0 + resolution: "@typescript-eslint/parser@npm:6.17.0" dependencies: - "@typescript-eslint/scope-manager": "npm:6.16.0" - "@typescript-eslint/types": "npm:6.16.0" - "@typescript-eslint/typescript-estree": "npm:6.16.0" - "@typescript-eslint/visitor-keys": "npm:6.16.0" + "@typescript-eslint/scope-manager": "npm:6.17.0" + "@typescript-eslint/types": "npm:6.17.0" + "@typescript-eslint/typescript-estree": "npm:6.17.0" + "@typescript-eslint/visitor-keys": "npm:6.17.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 3d941ce345dc2ce29957e2110957662873d514b094b8939923c3281d858c11cd1f9058db862644afe14f68d087770f39a0a1f9e523a2013ed5d2fdf3421b34d0 + checksum: 2ed0ed4a5b30e953430ce3279df3655af09fa1caed2abf11804d239717daefc32a22864f6620ef57bb9c684c74a99a13241384fea5096e961385e3678fc2e920 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.16.0": - version: 6.16.0 - resolution: "@typescript-eslint/scope-manager@npm:6.16.0" +"@typescript-eslint/scope-manager@npm:6.17.0": + version: 6.17.0 + resolution: "@typescript-eslint/scope-manager@npm:6.17.0" dependencies: - "@typescript-eslint/types": "npm:6.16.0" - "@typescript-eslint/visitor-keys": "npm:6.16.0" - checksum: 3360aae4b85f5c31d20ad48d771cc09a6f8f6b1811b00d94f06e55b5a09c610ac75631b1c4edecb3bec682d41351b87e7d14d42bee84aa032064d0e13463035b + "@typescript-eslint/types": "npm:6.17.0" + "@typescript-eslint/visitor-keys": "npm:6.17.0" + checksum: fe09c628553c9336e6a36d32c1d34e78ebd20aa02130a6bf535329621ba5a98aaac171f607bc6e4d17b3478c42e7de6476376636897ce3f227c754eb99acd07e languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.16.0": - version: 6.16.0 - resolution: "@typescript-eslint/type-utils@npm:6.16.0" +"@typescript-eslint/type-utils@npm:6.17.0": + version: 6.17.0 + resolution: "@typescript-eslint/type-utils@npm:6.17.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:6.16.0" - "@typescript-eslint/utils": "npm:6.16.0" + "@typescript-eslint/typescript-estree": "npm:6.17.0" + "@typescript-eslint/utils": "npm:6.17.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.0.1" peerDependencies: @@ -4629,23 +4629,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 5964b87a87252bed278a248eb568902babd7c34defd3af8c3df371926d96aec716f33f1dc14bde170e93f73ed1b0af6e591e647853d0f33f378e2c7b3b73fc5b + checksum: dc7938429193acfda61b7282197ec046039e2c4da41cdcddf4daaf300d10229e4e23bb0fcf0503b19c0b99a874849c8a9f5bb35ce106260f56a14106d2b41d8c languageName: node linkType: hard -"@typescript-eslint/types@npm:6.16.0": - version: 6.16.0 - resolution: "@typescript-eslint/types@npm:6.16.0" - checksum: 236ca318c2440c95068e5d4d147e2bfed62447775e18695e21c8ca04a341a74d01c37ed2b417629b7bf2fb91ad4fd5e2a6570215d16fc24dd1507ce6973b4e22 +"@typescript-eslint/types@npm:6.17.0": + version: 6.17.0 + resolution: "@typescript-eslint/types@npm:6.17.0" + checksum: 87ab1b5a3270ab34b917c22a2fb90a9ad7d9f3b19d73a337bc9efbe65f924da13482c97e8ccbe3bd3d081aa96039eeff50de41c1da2a2128066429b931cdb21d languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.16.0": - version: 6.16.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.16.0" +"@typescript-eslint/typescript-estree@npm:6.17.0": + version: 6.17.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.17.0" dependencies: - "@typescript-eslint/types": "npm:6.16.0" - "@typescript-eslint/visitor-keys": "npm:6.16.0" + "@typescript-eslint/types": "npm:6.17.0" + "@typescript-eslint/visitor-keys": "npm:6.17.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" @@ -4655,34 +4655,34 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 8e1ef03ecabaf3791b11240a51217836dbb74850e458258db77ac5eab5508cd9c63fb671924993d1e7654718c0c857c3550d51ecba0845fe489d143bb858e1b1 + checksum: 1671b0d2f2fdf07074fb1e2524d61935cec173bd8db6e482cc5b2dcc77aed3ffa831396736ffa0ee2fdbddd8585ae9ca8d6c97bcaea1385b23907a1ec0508f83 languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.16.0": - version: 6.16.0 - resolution: "@typescript-eslint/utils@npm:6.16.0" +"@typescript-eslint/utils@npm:6.17.0": + version: 6.17.0 + resolution: "@typescript-eslint/utils@npm:6.17.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" "@types/json-schema": "npm:^7.0.12" "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:6.16.0" - "@typescript-eslint/types": "npm:6.16.0" - "@typescript-eslint/typescript-estree": "npm:6.16.0" + "@typescript-eslint/scope-manager": "npm:6.17.0" + "@typescript-eslint/types": "npm:6.17.0" + "@typescript-eslint/typescript-estree": "npm:6.17.0" semver: "npm:^7.5.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 84dd02f7c8e47fae699cc222da5cbea08b28c6e1cc7827860430bc86c2a17ee3f86e198a4356902b95930f85785aa662266ea9c476f69bf80c6a5f648e55f9f4 + checksum: 37c63afcf66124bf84808699997953b8c84a378aa2c490a771b611d82cdac8499c58fac8eeb8378528e97660b59563d99297bfec4b982cd68760b0ffe54aa714 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.16.0": - version: 6.16.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.16.0" +"@typescript-eslint/visitor-keys@npm:6.17.0": + version: 6.17.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.17.0" dependencies: - "@typescript-eslint/types": "npm:6.16.0" + "@typescript-eslint/types": "npm:6.17.0" eslint-visitor-keys: "npm:^3.4.1" - checksum: 19e559f14ea0092585a374b8c5f1aca9b6b271fc23909d9857de9cf71a1e1d3abc0afd237e9c02d7a5fbdfe8e3be7853cf9fedf40a6f16bac3495cb7f4e67982 + checksum: a2aed0e1437fdab8858ab9c7c8e355f8b72a5fa4b0adc54f28b8a2bbc29d4bb93214968ee940f83d013d0a4b83d00cd4eeeb05fb4c2c7d0ead324c6793f7d6d4 languageName: node linkType: hard @@ -9610,8 +9610,8 @@ __metadata: "@types/tar": "npm:6.1.10" "@types/ua-parser-js": "npm:0.7.39" "@types/webspeechapi": "npm:0.0.29" - "@typescript-eslint/eslint-plugin": "npm:6.16.0" - "@typescript-eslint/parser": "npm:6.16.0" + "@typescript-eslint/eslint-plugin": "npm:6.17.0" + "@typescript-eslint/parser": "npm:6.17.0" "@vaadin/combo-box": "npm:24.3.2" "@vaadin/vaadin-themable-mixin": "npm:24.3.2" "@vibrant/color": "npm:3.2.1-alpha.1" From be7b3a56f9ca933f4869d6947310ddc2a0772f40 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 20:36:13 -0500 Subject: [PATCH 088/361] Update dependency core-js to v3.35.0 (#19215) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 492548711772..ce2e0a01eb14 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "app-datepicker": "5.1.1", "chart.js": "4.4.1", "comlink": "4.4.1", - "core-js": "3.34.0", + "core-js": "3.35.0", "cropperjs": "1.6.1", "date-fns": "2.30.0", "date-fns-tz": "2.0.0", diff --git a/yarn.lock b/yarn.lock index d96a28098a86..44814ecb620e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7024,10 +7024,10 @@ __metadata: languageName: node linkType: hard -"core-js@npm:3.34.0": - version: 3.34.0 - resolution: "core-js@npm:3.34.0" - checksum: 054474ab6a0a08a2277ca2c1c953e5789c562bbe144f6a43786b0f4167b4a76c671833bd0a112e275e1d99d84fa157e64814ff23aa01532e08e3b46403d7f7f4 +"core-js@npm:3.35.0": + version: 3.35.0 + resolution: "core-js@npm:3.35.0" + checksum: 0815fce6bcc91d79d4b28885975453b0faa4d17fc2230635102b4f3832cd621035e4032aa3307e1dbe0ee14d5e34bcb64b507fd89bd8f567aedaf29538522e6a languageName: node linkType: hard @@ -9628,7 +9628,7 @@ __metadata: chai: "npm:5.0.0" chart.js: "npm:4.4.1" comlink: "npm:4.4.1" - core-js: "npm:3.34.0" + core-js: "npm:3.35.0" cropperjs: "npm:1.6.1" date-fns: "npm:2.30.0" date-fns-tz: "npm:2.0.0" From 53be012b3454b4c1dd34a4bb30b20b2d96ae0008 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 20:42:11 -0500 Subject: [PATCH 089/361] Update CodeMirror (#19214) --- package.json | 8 ++++---- yarn.lock | 46 +++++++++++++++++++++++----------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index ce2e0a01eb14..a466d708db51 100644 --- a/package.json +++ b/package.json @@ -28,12 +28,12 @@ "@babel/runtime": "7.23.7", "@braintree/sanitize-url": "7.0.0", "@codemirror/autocomplete": "6.11.1", - "@codemirror/commands": "6.3.2", - "@codemirror/language": "6.9.3", + "@codemirror/commands": "6.3.3", + "@codemirror/language": "6.10.0", "@codemirror/legacy-modes": "6.3.3", "@codemirror/search": "6.5.5", - "@codemirror/state": "6.3.3", - "@codemirror/view": "6.22.3", + "@codemirror/state": "6.4.0", + "@codemirror/view": "6.23.0", "@egjs/hammerjs": "2.0.17", "@formatjs/intl-datetimeformat": "6.12.0", "@formatjs/intl-displaynames": "6.6.4", diff --git a/yarn.lock b/yarn.lock index 44814ecb620e..49ff1a2017b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1474,29 +1474,29 @@ __metadata: languageName: node linkType: hard -"@codemirror/commands@npm:6.3.2": - version: 6.3.2 - resolution: "@codemirror/commands@npm:6.3.2" +"@codemirror/commands@npm:6.3.3": + version: 6.3.3 + resolution: "@codemirror/commands@npm:6.3.3" dependencies: "@codemirror/language": "npm:^6.0.0" - "@codemirror/state": "npm:^6.2.0" + "@codemirror/state": "npm:^6.4.0" "@codemirror/view": "npm:^6.0.0" "@lezer/common": "npm:^1.1.0" - checksum: 85bf8242645e3f8c52b143883e837277795f9c50ad76f28f72d0d55ec921750f15ef5b4fa156b37e123b51e540d96c8db89b48bf0460cbe4a6f7b57271a65ba6 + checksum: 4b398b102d6afcbf0e0018b426287a7458867497811c9155790a3cc679b880765cd756bdb96bf35abc28fecb85c0938e618d39469ce8bc0724d4dea5d88f6ac2 languageName: node linkType: hard -"@codemirror/language@npm:6.9.3, @codemirror/language@npm:^6.0.0": - version: 6.9.3 - resolution: "@codemirror/language@npm:6.9.3" +"@codemirror/language@npm:6.10.0, @codemirror/language@npm:^6.0.0": + version: 6.10.0 + resolution: "@codemirror/language@npm:6.10.0" dependencies: "@codemirror/state": "npm:^6.0.0" - "@codemirror/view": "npm:^6.0.0" + "@codemirror/view": "npm:^6.23.0" "@lezer/common": "npm:^1.1.0" "@lezer/highlight": "npm:^1.0.0" "@lezer/lr": "npm:^1.0.0" style-mod: "npm:^4.0.0" - checksum: 331230a3876ed469cbf18dc2733040aa42a175b1a038080e4c317cf7f1fd8e929dc6838ba4749ea52992805f20be85878214cab6e0e7c7ab5fda872844611b7a + checksum: 674f87a5f7cae19a5e0cbdd0e06beade7f3694809cc30b31939aa04790dd43008942e3cd3b537ba5729fd14fed81c8ff62b7dcf51800db815cbf8d19d1d6a763 languageName: node linkType: hard @@ -1520,21 +1520,21 @@ __metadata: languageName: node linkType: hard -"@codemirror/state@npm:6.3.3, @codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.1.4, @codemirror/state@npm:^6.2.0": - version: 6.3.3 - resolution: "@codemirror/state@npm:6.3.3" - checksum: c0db0fc943ed36925238242522a8f4b2a4e3ecc4489cc013ea6d32be2bc615ecd813c98ff6a4c8f8ec1179376e555ec93a07dc1f0d1751aae721b5b38f812c08 +"@codemirror/state@npm:6.4.0, @codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.4.0": + version: 6.4.0 + resolution: "@codemirror/state@npm:6.4.0" + checksum: d9129c456d1589ca376594620bad10c51d3dcdb57950f34637cea0e2ea073a695d426dc1cfc9b909b07365c236a6312da1eaf740c384c853009742493b8c9935 languageName: node linkType: hard -"@codemirror/view@npm:6.22.3, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0": - version: 6.22.3 - resolution: "@codemirror/view@npm:6.22.3" +"@codemirror/view@npm:6.23.0, @codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0": + version: 6.23.0 + resolution: "@codemirror/view@npm:6.23.0" dependencies: - "@codemirror/state": "npm:^6.1.4" + "@codemirror/state": "npm:^6.4.0" style-mod: "npm:^4.1.0" w3c-keyname: "npm:^2.2.4" - checksum: c0ad3e9ab49ca9aba214cfe317e506f25d094bb3243cafd0309093279eb99084810f289a5cc019db6c35463813707bdc31557b28afb30d390f4736dd0dadc541 + checksum: 3fc1c39e6d0b2550d3f4e207705f953956baa7ce768eed0258373260db86f65ae3c1eea050e8fdfe3266d4f365828f90f4341cea71b0f0e4f19515a5341e5706 languageName: node linkType: hard @@ -9521,12 +9521,12 @@ __metadata: "@braintree/sanitize-url": "npm:7.0.0" "@bundle-stats/plugin-webpack-filter": "npm:4.8.4" "@codemirror/autocomplete": "npm:6.11.1" - "@codemirror/commands": "npm:6.3.2" - "@codemirror/language": "npm:6.9.3" + "@codemirror/commands": "npm:6.3.3" + "@codemirror/language": "npm:6.10.0" "@codemirror/legacy-modes": "npm:6.3.3" "@codemirror/search": "npm:6.5.5" - "@codemirror/state": "npm:6.3.3" - "@codemirror/view": "npm:6.22.3" + "@codemirror/state": "npm:6.4.0" + "@codemirror/view": "npm:6.23.0" "@egjs/hammerjs": "npm:2.0.17" "@formatjs/intl-datetimeformat": "npm:6.12.0" "@formatjs/intl-displaynames": "npm:6.6.4" From 7a8f5c0cc93722334cf20ff9012508ab691d1719 Mon Sep 17 00:00:00 2001 From: Simon Lamon <32477463+silamon@users.noreply.github.com> Date: Fri, 5 Jan 2024 14:31:58 +0100 Subject: [PATCH 090/361] Replace remaining paper inputs (#19292) --- .../components/supervisor-backup-content.ts | 36 +++++++-------- .../dialogs/network/dialog-hassio-network.ts | 46 +++++++++---------- .../dialog-hassio-repositories.ts | 10 ++-- package.json | 1 - yarn.lock | 39 ---------------- 5 files changed, 44 insertions(+), 88 deletions(-) diff --git a/hassio/src/components/supervisor-backup-content.ts b/hassio/src/components/supervisor-backup-content.ts index 8174debcefc5..ff67b511c023 100644 --- a/hassio/src/components/supervisor-backup-content.ts +++ b/hassio/src/components/supervisor-backup-content.ts @@ -1,6 +1,4 @@ import { mdiFolder, mdiPuzzle } from "@mdi/js"; -import "@polymer/paper-input/paper-input"; -import type { PaperInputElement } from "@polymer/paper-input/paper-input"; import { CSSResultGroup, LitElement, @@ -16,6 +14,7 @@ import { formatDateTime } from "../../../src/common/datetime/format_date_time"; import { LocalizeFunc } from "../../../src/common/translations/localize"; import "../../../src/components/ha-checkbox"; import "../../../src/components/ha-formfield"; +import "../../../src/components/ha-textfield"; import "../../../src/components/ha-radio"; import type { HaRadio } from "../../../src/components/ha-radio"; import { @@ -25,12 +24,9 @@ import { } from "../../../src/data/hassio/backup"; import { Supervisor } from "../../../src/data/supervisor/supervisor"; import { mdiHomeAssistant } from "../../../src/resources/home-assistant-logo-svg"; -import { - HomeAssistant, - TranslationDict, - ValueChangedEvent, -} from "../../../src/types"; +import { HomeAssistant, TranslationDict } from "../../../src/types"; import "./supervisor-formfield-label"; +import type { HaTextField } from "../../../src/components/ha-textfield"; type BackupOrRestoreKey = keyof TranslationDict["supervisor"]["backup"] & keyof TranslationDict["ui"]["panel"]["page-onboarding"]["restore"]; @@ -100,7 +96,7 @@ export class SupervisorBackupContent extends LitElement { @property() public confirmBackupPassword = ""; - @query("paper-input, ha-radio, ha-checkbox", true) private _focusTarget; + @query("ha-textfield, ha-radio, ha-checkbox", true) private _focusTarget; public willUpdate(changedProps) { super.willUpdate(changedProps); @@ -151,13 +147,13 @@ export class SupervisorBackupContent extends LitElement { ) : this.backup.date}

` - : html` - `} + `} ${!this.backup || this.backup.type === "full" ? html`
${!this.backup @@ -265,23 +261,23 @@ export class SupervisorBackupContent extends LitElement { : ""} ${this.backupHasPassword ? html` - - + ${!this.backup - ? html` - ` + ` : ""} ` : ""} @@ -429,9 +425,9 @@ export class SupervisorBackupContent extends LitElement { this[input.name] = input.value; } - private _handleTextValueChanged(ev: ValueChangedEvent) { - const input = ev.currentTarget as PaperInputElement; - this[input.name!] = ev.detail.value; + private _handleTextValueChanged(ev: InputEvent) { + const input = ev.currentTarget as HaTextField; + this[input.name!] = input.value; } private _toggleHasPassword(): void { diff --git a/hassio/src/dialogs/network/dialog-hassio-network.ts b/hassio/src/dialogs/network/dialog-hassio-network.ts index c831fb6c221d..b36b734a08e8 100644 --- a/hassio/src/dialogs/network/dialog-hassio-network.ts +++ b/hassio/src/dialogs/network/dialog-hassio-network.ts @@ -4,7 +4,6 @@ import "@material/mwc-list/mwc-list-item"; import "@material/mwc-tab"; import "@material/mwc-tab-bar"; import { mdiClose } from "@mdi/js"; -import { PaperInputElement } from "@polymer/paper-input/paper-input"; import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { cache } from "lit/directives/cache"; @@ -14,6 +13,7 @@ import "../../../../src/components/ha-circular-progress"; import "../../../../src/components/ha-dialog"; import "../../../../src/components/ha-expansion-panel"; import "../../../../src/components/ha-formfield"; +import "../../../../src/components/ha-textfield"; import "../../../../src/components/ha-header-bar"; import "../../../../src/components/ha-icon-button"; import "../../../../src/components/ha-radio"; @@ -34,6 +34,7 @@ import { HassDialog } from "../../../../src/dialogs/make-dialog-manager"; import { haStyleDialog } from "../../../../src/resources/styles"; import type { HomeAssistant } from "../../../../src/types"; import { HassioNetworkDialogParams } from "./show-dialog-network"; +import type { HaTextField } from "../../../../src/components/ha-textfield"; const IP_VERSIONS = ["ipv4", "ipv6"]; @@ -245,7 +246,7 @@ export class DialogHassioNetwork ${this._wifiConfiguration.auth === "wpa-psk" || this._wifiConfiguration.auth === "wep" ? html` - - + ` : ""} ` @@ -358,33 +358,33 @@ export class DialogHassioNetwork
${this._interface![version].method === "static" ? html` - - - + - - + - + ` : ""} @@ -517,11 +517,11 @@ export class DialogHassioNetwork this.requestUpdate("_wifiConfiguration"); } - private _handleInputValueChanged(ev: CustomEvent): void { - const value: string | null | undefined = (ev.target as PaperInputElement) - .value; + private _handleInputValueChanged(ev: Event): void { + const source = ev.target as HaTextField; + const value = source.value; const version = (ev.target as any).version as "ipv4" | "ipv6"; - const id = (ev.target as PaperInputElement).id; + const id = source.id; if ( !value || @@ -535,10 +535,10 @@ export class DialogHassioNetwork this._interface[version]![id] = value; } - private _handleInputValueChangedWifi(ev: CustomEvent): void { - const value: string | null | undefined = (ev.target as PaperInputElement) - .value; - const id = (ev.target as PaperInputElement).id; + private _handleInputValueChangedWifi(ev: Event): void { + const source = ev.target as HaTextField; + const value = source.value; + const id = source.id; if ( !value || @@ -630,7 +630,7 @@ export class DialogHassioNetwork --expansion-panel-summary-padding: 0 16px; margin: 4px 0; } - paper-input { + ha-textfield { padding: 0 14px; } mwc-list-item { diff --git a/hassio/src/dialogs/repositories/dialog-hassio-repositories.ts b/hassio/src/dialogs/repositories/dialog-hassio-repositories.ts index 98dfc32b2417..5443d7ed44c1 100644 --- a/hassio/src/dialogs/repositories/dialog-hassio-repositories.ts +++ b/hassio/src/dialogs/repositories/dialog-hassio-repositories.ts @@ -1,7 +1,5 @@ import "@material/mwc-button/mwc-button"; import { mdiDelete, mdiDeleteOff } from "@mdi/js"; -import "@polymer/paper-input/paper-input"; -import type { PaperInputElement } from "@polymer/paper-input/paper-input"; import "@polymer/paper-item/paper-item"; import "@polymer/paper-item/paper-item-body"; import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; @@ -27,12 +25,14 @@ import { import { haStyle, haStyleDialog } from "../../../../src/resources/styles"; import type { HomeAssistant } from "../../../../src/types"; import { HassioRepositoryDialogParams } from "./show-dialog-repositories"; +import type { HaTextField } from "../../../../src/components/ha-textfield"; +import "../../../../src/components/ha-textfield"; @customElement("dialog-hassio-repositories") class HassioRepositoriesDialog extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @query("#repository_input", true) private _optionInput?: PaperInputElement; + @query("#repository_input", true) private _optionInput?: HaTextField; @state() private _repositories?: HassioAddonRepository[]; @@ -145,7 +145,7 @@ class HassioRepositoriesDialog extends LitElement { ) : html` No repositories `}
- + > ${this._processing ? html` Date: Fri, 5 Jan 2024 15:56:15 +0200 Subject: [PATCH 091/361] Fix for RTL in Supervisor dashboards (#19290) --- hassio/src/dashboard/hassio-addons.ts | 1 + hassio/src/dashboard/hassio-dashboard.ts | 2 ++ hassio/src/supervisor-base-element.ts | 10 ++++++++++ 3 files changed, 13 insertions(+) diff --git a/hassio/src/dashboard/hassio-addons.ts b/hassio/src/dashboard/hassio-addons.ts index 7b3c9d166f0e..daeb867ef66d 100644 --- a/hassio/src/dashboard/hassio-addons.ts +++ b/hassio/src/dashboard/hassio-addons.ts @@ -128,6 +128,7 @@ class HassioAddons extends LitElement { ha-card { cursor: pointer; overflow: hidden; + direction: ltr; } .search { position: sticky; diff --git a/hassio/src/dashboard/hassio-dashboard.ts b/hassio/src/dashboard/hassio-dashboard.ts index d60819861c15..a38c37b8a822 100644 --- a/hassio/src/dashboard/hassio-dashboard.ts +++ b/hassio/src/dashboard/hassio-dashboard.ts @@ -133,6 +133,8 @@ class HassioDashboard extends LitElement { position: fixed; right: calc(16px + env(safe-area-inset-right)); bottom: calc(16px + env(safe-area-inset-bottom)); + inset-inline-end: calc(16px + env(safe-area-inset-right)); + inset-inline-start: initial; z-index: 1; } `, diff --git a/hassio/src/supervisor-base-element.ts b/hassio/src/supervisor-base-element.ts index 9402728160de..86dc81998887 100644 --- a/hassio/src/supervisor-base-element.ts +++ b/hassio/src/supervisor-base-element.ts @@ -29,6 +29,10 @@ import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin"; import { urlSyncMixin } from "../../src/state/url-sync-mixin"; import { HomeAssistant, Route } from "../../src/types"; import { getTranslation } from "../../src/util/common-translation"; +import { + computeRTLDirection, + setDirectionStyles, +} from "../../src/common/util/compute_rtl"; declare global { interface HASSDomEvents { @@ -95,6 +99,7 @@ export class SupervisorBaseElement extends urlSyncMixin( if (changedProperties.has("_language") || !this.hasUpdated) { this._initializeLocalize(); + this._applyDirection(this.hass); } } @@ -215,4 +220,9 @@ export class SupervisorBaseElement extends urlSyncMixin( ); } } + + private _applyDirection(hass: HomeAssistant) { + const direction = computeRTLDirection(hass); + setDirectionStyles(direction, this); + } } From 8960f5fef9b32a1b4c11949783b26bec5f3dd087 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 6 Jan 2024 20:50:10 -0500 Subject: [PATCH 092/361] Update dependency @types/luxon to v3.3.8 (#19308) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index b7a0cba7a7ca..0c7a6998ca19 100644 --- a/package.json +++ b/package.json @@ -175,7 +175,7 @@ "@types/js-yaml": "4.0.9", "@types/leaflet": "1.9.8", "@types/leaflet-draw": "1.0.11", - "@types/luxon": "3.3.7", + "@types/luxon": "3.3.8", "@types/mocha": "10.0.6", "@types/qrcode": "1.5.5", "@types/serve-handler": "6.1.4", diff --git a/yarn.lock b/yarn.lock index c43ac1d4b56f..ef48030ab766 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4271,10 +4271,10 @@ __metadata: languageName: node linkType: hard -"@types/luxon@npm:3.3.7": - version: 3.3.7 - resolution: "@types/luxon@npm:3.3.7" - checksum: 282ac72fd55da0c9d57f376ba9061ce83506cf6239c32259dacde0800964089f6183d2e449ef2ddd89b079fb8bfdffd7e5dbf187eb5c9f106aeaeca2aa60ed09 +"@types/luxon@npm:3.3.8": + version: 3.3.8 + resolution: "@types/luxon@npm:3.3.8" + checksum: 2176c394e7ee3b8580e9f30bedac29048fabe32589c6561a9654b242b9c2c08ff9b93206f0eca07e495f900a352ac1446236c310eacda574b3c2d6238a9173a7 languageName: node linkType: hard @@ -9563,7 +9563,7 @@ __metadata: "@types/js-yaml": "npm:4.0.9" "@types/leaflet": "npm:1.9.8" "@types/leaflet-draw": "npm:1.0.11" - "@types/luxon": "npm:3.3.7" + "@types/luxon": "npm:3.3.8" "@types/mocha": "npm:10.0.6" "@types/qrcode": "npm:1.5.5" "@types/serve-handler": "npm:6.1.4" From 90965a4f4db29fdb03647c16c9000c6bcdc99244 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Sat, 6 Jan 2024 20:19:44 -0800 Subject: [PATCH 093/361] Localize statistics datatable string (#19289) --- .../developer-tools/statistics/developer-tools-statistics.ts | 4 +++- src/translations/en.json | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/panels/developer-tools/statistics/developer-tools-statistics.ts b/src/panels/developer-tools/statistics/developer-tools-statistics.ts index 878a4fa73978..25339a91e27c 100644 --- a/src/panels/developer-tools/statistics/developer-tools-statistics.ts +++ b/src/panels/developer-tools/statistics/developer-tools-statistics.ts @@ -177,7 +177,9 @@ class HaPanelDevStatistics extends SubscribeMixin(LitElement) { .hass=${this.hass} .columns=${this._columns(this.hass.localize)} .data=${this._displayData(this._data, this.hass.localize)} - noDataText="No statistics" + .noDataText=${this.hass.localize( + "ui.panel.developer-tools.tabs.statistics.data_table.no_statistics" + )} id="statistic_id" clickable @row-click=${this._rowClicked} diff --git a/src/translations/en.json b/src/translations/en.json index 74467bcbf1ab..01cd81a568e1 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -6190,7 +6190,8 @@ "statistic_id": "Statistic id", "statistics_unit": "Statistics unit", "source": "Source", - "issue": "Issue" + "issue": "Issue", + "no_statistics": "[%key:ui::components::statistics_charts::no_statistics_found%]" } }, "yaml": { From 17e62c10d49d1823cab2874deae88232ca92e6f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 08:17:13 +0100 Subject: [PATCH 094/361] Bump home-assistant/wheels from 2023.10.5 to 2024.01.0 (#19321) --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8bded3fcc5e2..dc843252dd02 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -74,7 +74,7 @@ jobs: echo "home-assistant-frontend==$version" > ./requirements.txt - name: Build wheels - uses: home-assistant/wheels@2023.10.5 + uses: home-assistant/wheels@2024.01.0 with: abi: cp311 tag: musllinux_1_2 From 104aef3dec2e8856d5323aecad9fea9666301776 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 8 Jan 2024 14:02:41 +0100 Subject: [PATCH 095/361] Add ha-sortable component (#19294) --- .../ha-selector/ha-selector-select.ts | 175 ++++---- src/components/ha-sidebar.ts | 111 ++--- src/components/ha-sortable.ts | 153 +++++++ src/dialogs/area-filter/area-filter-dialog.ts | 144 +++---- .../ha-more-info-light-favorite-colors.ts | 182 ++++---- .../automation/action/ha-automation-action.ts | 221 +++++----- .../types/ha-automation-action-choose.ts | 387 ++++++++---------- .../condition/ha-automation-condition.ts | 228 +++++------ .../trigger/ha-automation-trigger.ts | 233 +++++------ .../helpers/forms/ha-input_select-form.ts | 122 ++---- src/panels/config/script/ha-script-fields.ts | 24 +- .../lovelace/cards/hui-todo-list-card.ts | 320 +++++++-------- .../lovelace/components/hui-entity-editor.ts | 160 +++----- .../hui-card-features-editor.ts | 310 ++++++-------- .../editor/hui-entities-card-row-editor.ts | 279 ++++++------- ...able-style.ts => ha-sidebar-edit-style.ts} | 30 +- 16 files changed, 1371 insertions(+), 1708 deletions(-) create mode 100644 src/components/ha-sortable.ts rename src/resources/{ha-sortable-style.ts => ha-sidebar-edit-style.ts} (74%) diff --git a/src/components/ha-selector/ha-selector-select.ts b/src/components/ha-selector/ha-selector-select.ts index a20559f91bfe..0f1301d28680 100644 --- a/src/components/ha-selector/ha-selector-select.ts +++ b/src/components/ha-selector/ha-selector-select.ts @@ -1,16 +1,13 @@ import "@material/mwc-list/mwc-list-item"; import { mdiDrag } from "@mdi/js"; -import { LitElement, PropertyValues, css, html, nothing } from "lit"; +import { LitElement, css, html, nothing } from "lit"; import { customElement, property, query } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import { SortableEvent } from "sortablejs"; import { ensureArray } from "../../common/array/ensure-array"; import { fireEvent } from "../../common/dom/fire_event"; import { stopPropagation } from "../../common/dom/stop_propagation"; import { caseInsensitiveStringCompare } from "../../common/string/compare"; import type { SelectOption, SelectSelector } from "../../data/selector"; -import { sortableStyles } from "../../resources/ha-sortable-style"; -import { SortableInstance } from "../../resources/sortable"; import type { HomeAssistant } from "../../types"; import "../chips/ha-chip-set"; import "../chips/ha-input-chip"; @@ -21,6 +18,7 @@ import "../ha-formfield"; import "../ha-input-helper-text"; import "../ha-radio"; import "../ha-select"; +import "../ha-sortable"; @customElement("ha-selector-select") export class HaSelectSelector extends LitElement { @@ -42,50 +40,10 @@ export class HaSelectSelector extends LitElement { @query("ha-combo-box", true) private comboBox!: HaComboBox; - private _sortable?: SortableInstance; - - protected updated(changedProps: PropertyValues): void { - if (changedProps.has("value") || changedProps.has("selector")) { - const sortableNeeded = - this.selector.select?.multiple && - this.selector.select.reorder && - this.value?.length; - if (!this._sortable && sortableNeeded) { - this._createSortable(); - } else if (this._sortable && !sortableNeeded) { - this._destroySortable(); - } - } - } - - private async _createSortable() { - const Sortable = (await import("../../resources/sortable")).default; - this._sortable = new Sortable( - this.shadowRoot!.querySelector("ha-chip-set")!, - { - animation: 150, - fallbackClass: "sortable-fallback", - draggable: "ha-input-chip", - onChoose: (evt: SortableEvent) => { - (evt.item as any).placeholder = - document.createComment("sort-placeholder"); - evt.item.after((evt.item as any).placeholder); - }, - onEnd: (evt: SortableEvent) => { - // put back in original location - if ((evt.item as any).placeholder) { - (evt.item as any).placeholder.replaceWith(evt.item); - delete (evt.item as any).placeholder; - } - this._dragged(evt); - }, - } - ); - } - - private _dragged(ev: SortableEvent): void { - if (ev.oldIndex === ev.newIndex) return; - this._move(ev.oldIndex!, ev.newIndex!); + private _itemMoved(ev: CustomEvent): void { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; + this._move(oldIndex!, newIndex); } private _move(index: number, newIndex: number) { @@ -99,11 +57,6 @@ export class HaSelectSelector extends LitElement { }); } - private _destroySortable() { - this._sortable?.destroy(); - this._sortable = undefined; - } - private _filter = ""; protected render() { @@ -195,37 +148,43 @@ export class HaSelectSelector extends LitElement { return html` ${value?.length ? html` - - ${repeat( - value, - (item) => item, - (item, idx) => { - const label = - options.find((option) => option.value === item)?.label || - item; - return html` - - ${this.selector.select?.reorder - ? html` - - ` - : nothing} - ${options.find((option) => option.value === item) - ?.label || item} - - `; - } - )} - + + + ${repeat( + value, + (item) => item, + (item, idx) => { + const label = + options.find((option) => option.value === item) + ?.label || item; + return html` + + ${this.selector.select?.reorder + ? html` + + ` + : nothing} + ${options.find((option) => option.value === item) + ?.label || item} + + `; + } + )} + + ` : nothing} @@ -419,25 +378,35 @@ export class HaSelectSelector extends LitElement { this.comboBox.filteredItems = filteredItems; } - static styles = [ - sortableStyles, - css` - :host { - position: relative; - } - ha-select, - mwc-formfield, - ha-formfield { - display: block; - } - mwc-list-item[disabled] { - --mdc-theme-text-primary-on-background: var(--disabled-text-color); - } - ha-chip-set { - padding: 8px 0; - } - `, - ]; + static styles = css` + :host { + position: relative; + } + ha-select, + mwc-formfield, + ha-formfield { + display: block; + } + mwc-list-item[disabled] { + --mdc-theme-text-primary-on-background: var(--disabled-text-color); + } + ha-chip-set { + padding: 8px 0; + } + + .sortable-fallback { + display: none; + opacity: 0; + } + + .sortable-ghost { + opacity: 0.4; + } + + .sortable-drag { + cursor: grabbing; + } + `; } declare global { diff --git a/src/components/ha-sidebar.ts b/src/components/ha-sidebar.ts index 50b5e1cba96c..352f0130f98c 100644 --- a/src/components/ha-sidebar.ts +++ b/src/components/ha-sidebar.ts @@ -33,7 +33,6 @@ import { } from "lit"; import { customElement, eventOptions, property, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; -import { guard } from "lit/directives/guard"; import memoizeOne from "memoize-one"; import { storage } from "../common/decorators/storage"; import { fireEvent } from "../common/dom/fire_event"; @@ -50,12 +49,12 @@ import { subscribeRepairsIssueRegistry } from "../data/repairs"; import { UpdateEntity, updateCanInstall } from "../data/update"; import { SubscribeMixin } from "../mixins/subscribe-mixin"; import { actionHandler } from "../panels/lovelace/common/directives/action-handler-directive"; -import type { SortableInstance } from "../resources/sortable"; import { haStyleScrollbar } from "../resources/styles"; import type { HomeAssistant, PanelInfo, Route } from "../types"; import "./ha-icon"; import "./ha-icon-button"; import "./ha-menu-button"; +import "./ha-sortable"; import "./ha-svg-icon"; import "./user/ha-user-badge"; @@ -204,15 +203,13 @@ class HaSidebar extends SubscribeMixin(LitElement) { @state() private _issuesCount = 0; - @state() private _renderEmptySortable = false; - private _mouseLeaveTimeout?: number; private _tooltipHideTimeout?: number; private _recentKeydownActiveUntil = 0; - private sortableStyleLoaded = false; + private _editStyleLoaded = false; @storage({ key: "sidebarPanelOrder", @@ -228,8 +225,6 @@ class HaSidebar extends SubscribeMixin(LitElement) { }) private _hiddenPanels: string[] = []; - private _sortable?: SortableInstance; - public hassSubscribe(): UnsubscribeFunc[] { return this.hass.user?.is_admin ? [ @@ -264,14 +259,13 @@ class HaSidebar extends SubscribeMixin(LitElement) { changedProps.has("expanded") || changedProps.has("narrow") || changedProps.has("alwaysExpand") || + changedProps.has("editMode") || changedProps.has("_externalConfig") || changedProps.has("_updatesCount") || changedProps.has("_issuesCount") || changedProps.has("_notifications") || - changedProps.has("editMode") || - changedProps.has("_renderEmptySortable") || changedProps.has("_hiddenPanels") || - (changedProps.has("_panelOrder") && !this.editMode) + changedProps.has("_panelOrder") ) { return true; } @@ -306,12 +300,8 @@ class HaSidebar extends SubscribeMixin(LitElement) { if (changedProps.has("alwaysExpand")) { toggleAttribute(this, "expanded", this.alwaysExpand); } - if (changedProps.has("editMode")) { - if (this.editMode) { - this._activateEditMode(); - } else { - this._deactivateEditMode(); - } + if (changedProps.has("editMode") && this.editMode) { + this._editModeActivated(); } if (!changedProps.has("hass")) { return; @@ -470,15 +460,36 @@ class HaSidebar extends SubscribeMixin(LitElement) { `; } + private _panelMoved(ev: CustomEvent) { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; + + const [beforeSpacer] = computePanels( + this.hass.panels, + this.hass.defaultPanel, + this._panelOrder, + this._hiddenPanels, + this.hass.locale + ); + + const panelOrder = beforeSpacer.map((panel) => panel.url_path); + const panel = panelOrder.splice(oldIndex, 1)[0]; + panelOrder.splice(newIndex, 0, panel); + + this._panelOrder = panelOrder; + } + private _renderPanelsEdit(beforeSpacer: PanelInfo[]) { - // prettier-ignore - return html`
- ${guard([this._hiddenPanels, this._renderEmptySortable], () => - this._renderEmptySortable ? "" : this._renderPanels(beforeSpacer) - )} -
- ${this._renderSpacer()} - ${this._renderHiddenPanels()} `; + return html` + +
${this._renderPanels(beforeSpacer)}
+
+ ${this._renderSpacer()}${this._renderHiddenPanels()} + `; } private _renderHiddenPanels() { @@ -674,44 +685,22 @@ class HaSidebar extends SubscribeMixin(LitElement) { fireEvent(this, "hass-edit-sidebar", { editMode: true }); } - private async _activateEditMode() { - await Promise.all([this._loadSortableStyle(), this._createSortable()]); + private async _editModeActivated() { + await this._loadEditStyle(); } - private async _loadSortableStyle() { - if (this.sortableStyleLoaded) return; + private async _loadEditStyle() { + if (this._editStyleLoaded) return; - const sortStylesImport = await import("../resources/ha-sortable-style"); + const editStylesImport = await import("../resources/ha-sidebar-edit-style"); const style = document.createElement("style"); - style.innerHTML = (sortStylesImport.sortableStyles as CSSResult).cssText; + style.innerHTML = (editStylesImport.sidebarEditStyle as CSSResult).cssText; this.shadowRoot!.appendChild(style); - this.sortableStyleLoaded = true; await this.updateComplete; } - private async _createSortable() { - const Sortable = (await import("../resources/sortable")).default; - this._sortable = new Sortable( - this.shadowRoot!.getElementById("sortable")!, - { - animation: 150, - fallbackClass: "sortable-fallback", - dataIdAttr: "data-panel", - handle: "paper-icon-item", - onSort: async () => { - this._panelOrder = this._sortable!.toArray(); - }, - } - ); - } - - private _deactivateEditMode() { - this._sortable?.destroy(); - this._sortable = undefined; - } - private _closeEditMode() { fireEvent(this, "hass-edit-sidebar", { editMode: false }); } @@ -724,13 +713,8 @@ class HaSidebar extends SubscribeMixin(LitElement) { } // Make a copy for Memoize this._hiddenPanels = [...this._hiddenPanels, panel]; - this._renderEmptySortable = true; - await this.updateComplete; - const container = this.shadowRoot!.getElementById("sortable")!; - while (container.lastElementChild) { - container.removeChild(container.lastElementChild); - } - this._renderEmptySortable = false; + // Remove it from the panel order + this._panelOrder = this._panelOrder.filter((order) => order !== panel); } private async _unhidePanel(ev: Event) { @@ -739,13 +723,6 @@ class HaSidebar extends SubscribeMixin(LitElement) { this._hiddenPanels = this._hiddenPanels.filter( (hidden) => hidden !== panel ); - this._renderEmptySortable = true; - await this.updateComplete; - const container = this.shadowRoot!.getElementById("sortable")!; - while (container.lastElementChild) { - container.removeChild(container.lastElementChild); - } - this._renderEmptySortable = false; } private _itemMouseEnter(ev: MouseEvent) { @@ -910,7 +887,7 @@ class HaSidebar extends SubscribeMixin(LitElement) { .menu mwc-button { width: 100%; } - #sortable, + .reorder-list, .hidden-panel { display: none; } diff --git a/src/components/ha-sortable.ts b/src/components/ha-sortable.ts new file mode 100644 index 000000000000..aed068a83af7 --- /dev/null +++ b/src/components/ha-sortable.ts @@ -0,0 +1,153 @@ +/* eslint-disable lit/prefer-static-styles */ +import { html, LitElement, nothing, PropertyValues } from "lit"; +import { customElement, property } from "lit/decorators"; +import type { SortableEvent } from "sortablejs"; +import { fireEvent } from "../common/dom/fire_event"; +import type { SortableInstance } from "../resources/sortable"; + +declare global { + interface HASSDomEvents { + "item-moved": { + oldIndex: number; + newIndex: number; + }; + } +} + +@customElement("ha-sortable") +export class HaSortable extends LitElement { + private _sortable?: SortableInstance; + + @property({ type: Boolean }) + public disabled = false; + + @property({ type: Boolean, attribute: "no-style" }) + public noStyle: boolean = false; + + @property({ type: String, attribute: "draggable-selector" }) + public draggableSelector?: string; + + @property({ type: String, attribute: "handle-selector" }) + public handleSelector?: string; + + protected updated(changedProperties: PropertyValues) { + if (changedProperties.has("disabled")) { + if (this.disabled) { + this._destroySortable(); + } else { + this._createSortable(); + } + } + } + + // Workaround for connectedCallback just after disconnectedCallback (when dragging sortable with sortable children) + private _shouldBeDestroy = false; + + public disconnectedCallback() { + super.disconnectedCallback(); + this._shouldBeDestroy = true; + setTimeout(() => { + if (this._shouldBeDestroy) { + this._destroySortable(); + this._shouldBeDestroy = false; + } + }, 1); + } + + public connectedCallback() { + super.connectedCallback(); + this._shouldBeDestroy = false; + } + + protected createRenderRoot() { + return this; + } + + protected render() { + if (this.noStyle) return nothing; + return html` + + `; + } + + private async _createSortable() { + if (this._sortable) return; + const container = this.children[0] as HTMLElement | undefined; + + if (!container) return; + + const Sortable = (await import("../resources/sortable")).default; + + const options: SortableInstance.Options = { + animation: 150, + onChoose: this._handleChoose, + onEnd: this._handleEnd, + }; + + if (this.draggableSelector) { + options.draggable = this.draggableSelector; + } + if (this.handleSelector) { + options.handle = this.handleSelector; + } + this._sortable = new Sortable(container, options); + } + + private _handleEnd = (evt: SortableEvent) => { + // put back in original location + if ((evt.item as any).placeholder) { + (evt.item as any).placeholder.replaceWith(evt.item); + delete (evt.item as any).placeholder; + } + // if item was not moved, ignore + if ( + evt.oldIndex === undefined || + evt.newIndex === undefined || + evt.oldIndex === evt.newIndex + ) { + return; + } + + fireEvent(this, "item-moved", { + oldIndex: evt.oldIndex!, + newIndex: evt.newIndex!, + }); + }; + + private _handleChoose = (evt: SortableEvent) => { + (evt.item as any).placeholder = document.createComment("sort-placeholder"); + evt.item.after((evt.item as any).placeholder); + }; + + private _destroySortable() { + if (!this._sortable) return; + this._sortable.destroy(); + this._sortable = undefined; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-sortable": HaSortable; + } +} diff --git a/src/dialogs/area-filter/area-filter-dialog.ts b/src/dialogs/area-filter/area-filter-dialog.ts index 2dc7cacadcb2..d82a515c0929 100644 --- a/src/dialogs/area-filter/area-filter-dialog.ts +++ b/src/dialogs/area-filter/area-filter-dialog.ts @@ -4,15 +4,13 @@ import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { repeat } from "lit/directives/repeat"; -import type { SortableEvent } from "sortablejs"; import { fireEvent } from "../../common/dom/fire_event"; import type { AreaFilterValue } from "../../components/ha-area-filter"; import "../../components/ha-button"; import "../../components/ha-icon-button"; import "../../components/ha-list-item"; +import "../../components/ha-sortable"; import { areaCompare } from "../../data/area_registry"; -import { sortableStyles } from "../../resources/ha-sortable-style"; -import type { SortableInstance } from "../../resources/sortable"; import { haStyleDialog } from "../../resources/styles"; import { HomeAssistant } from "../../types"; import { HassDialog } from "../make-dialog-manager"; @@ -31,23 +29,18 @@ export class DialogAreaFilter @state() private _areas: string[] = []; - private _sortable?: SortableInstance; - - public async showDialog(dialogParams: AreaFilterDialogParams): Promise { + public showDialog(dialogParams: AreaFilterDialogParams): void { this._dialogParams = dialogParams; this._hidden = dialogParams.initialValue?.hidden ?? []; const order = dialogParams.initialValue?.order ?? []; const allAreas = Object.keys(this.hass!.areas); this._areas = allAreas.concat().sort(areaCompare(this.hass!.areas, order)); - await this.updateComplete; - this._createSortable(); } public closeDialog(): void { this._dialogParams = undefined; this._hidden = []; this._areas = []; - this._destroySortable(); fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -66,42 +59,14 @@ export class DialogAreaFilter this.closeDialog(); } - private async _createSortable() { - const Sortable = (await import("../../resources/sortable")).default; - if (this._sortable) return; - this._sortable = new Sortable(this.shadowRoot!.querySelector(".areas")!, { - animation: 150, - fallbackClass: "sortable-fallback", - handle: ".handle", - draggable: ".draggable", - onChoose: (evt: SortableEvent) => { - (evt.item as any).placeholder = - document.createComment("sort-placeholder"); - evt.item.after((evt.item as any).placeholder); - }, - onEnd: (evt: SortableEvent) => { - // put back in original location - if ((evt.item as any).placeholder) { - (evt.item as any).placeholder.replaceWith(evt.item); - delete (evt.item as any).placeholder; - } - this._dragged(evt); - }, - }); - } - - private _destroySortable() { - this._sortable?.destroy(); - this._sortable = undefined; - } - - private _dragged(ev: SortableEvent): void { - if (ev.oldIndex === ev.newIndex) return; + private _areaMoved(ev: CustomEvent): void { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; const areas = this._areas.concat(); - const option = areas.splice(ev.oldIndex!, 1)[0]; - areas.splice(ev.newIndex!, 0, option); + const option = areas.splice(oldIndex, 1)[0]; + areas.splice(newIndex, 0, option); this._areas = areas; } @@ -120,50 +85,56 @@ export class DialogAreaFilter .heading=${this._dialogParams.title ?? this.hass.localize("ui.components.area-filter.title")} > - - ${repeat( - allAreas, - (area) => area, - (area, _idx) => { - const isVisible = !this._hidden.includes(area); - const name = this.hass!.areas[area]?.name || area; - return html` - - ${isVisible - ? html`` - : nothing} - ${name} - - - `; - } - )} - + + + ${repeat( + allAreas, + (area) => area, + (area, _idx) => { + const isVisible = !this._hidden.includes(area); + const name = this.hass!.areas[area]?.name || area; + return html` + + ${isVisible + ? html`` + : nothing} + ${name} + + + `; + } + )} + + ${this.hass.localize("ui.common.cancel")} @@ -192,7 +163,6 @@ export class DialogAreaFilter static get styles(): CSSResultGroup { return [ - sortableStyles, haStyleDialog, css` ha-dialog { diff --git a/src/dialogs/more-info/components/lights/ha-more-info-light-favorite-colors.ts b/src/dialogs/more-info/components/lights/ha-more-info-light-favorite-colors.ts index 9a2cbd6caf31..93a6b1528fd5 100644 --- a/src/dialogs/more-info/components/lights/ha-more-info-light-favorite-colors.ts +++ b/src/dialogs/more-info/components/lights/ha-more-info-light-favorite-colors.ts @@ -10,9 +10,9 @@ import { } from "lit"; import { customElement, property, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; -import type { SortableEvent } from "sortablejs"; import { fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/ha-control-slider"; +import "../../../../components/ha-sortable"; import { UNAVAILABLE } from "../../../../data/entity"; import { ExtEntityRegistryEntry, @@ -24,7 +24,6 @@ import { computeDefaultFavoriteColors, } from "../../../../data/light"; import { actionHandler } from "../../../../panels/lovelace/common/directives/action-handler-directive"; -import type { SortableInstance } from "../../../../resources/sortable"; import { HomeAssistant } from "../../../../types"; import { showConfirmationDialog } from "../../../generic/show-dialog-box"; import "./ha-favorite-color-button"; @@ -48,16 +47,7 @@ export class HaMoreInfoLightFavoriteColors extends LitElement { @state() private _favoriteColors: LightColor[] = []; - private _sortable?: SortableInstance; - protected updated(changedProps: PropertyValues): void { - if (changedProps.has("editMode")) { - if (this.editMode) { - this._createSortable(); - } else { - this._destroySortable(); - } - } if (changedProps.has("entry")) { if (this.entry) { if (this.entry.options?.light?.favorite_colors) { @@ -69,34 +59,10 @@ export class HaMoreInfoLightFavoriteColors extends LitElement { } } - private async _createSortable() { - const Sortable = (await import("../../../../resources/sortable")).default; - this._sortable = new Sortable( - this.shadowRoot!.querySelector(".container")!, - { - animation: 150, - fallbackClass: "sortable-fallback", - draggable: ".color", - onChoose: (evt: SortableEvent) => { - (evt.item as any).placeholder = - document.createComment("sort-placeholder"); - evt.item.after((evt.item as any).placeholder); - }, - onEnd: (evt: SortableEvent) => { - // put back in original location - if ((evt.item as any).placeholder) { - (evt.item as any).placeholder.replaceWith(evt.item); - delete (evt.item as any).placeholder; - } - this._dragged(evt); - }, - } - ); - } - - private _dragged(ev: SortableEvent): void { - if (ev.oldIndex === ev.newIndex) return; - this._move(ev.oldIndex!, ev.newIndex!); + private _colorMoved(ev: CustomEvent): void { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; + this._move(oldIndex, newIndex); } private _move(index: number, newIndex: number) { @@ -107,11 +73,6 @@ export class HaMoreInfoLightFavoriteColors extends LitElement { this._save(favoriteColors); } - private _destroySortable() { - this._sortable?.destroy(); - this._sortable = undefined; - } - private _apply = (index: number) => { const favorite = this._favoriteColors[index]; this.hass.callService("light", "turn_on", { @@ -223,72 +184,79 @@ export class HaMoreInfoLightFavoriteColors extends LitElement { protected render(): TemplateResult { return html` -
- ${this._favoriteColors.map( - (color, index) => html` -
-
- +
+ ${this._favoriteColors.map( + (color, index) => html` +
+
- - ${this.editMode - ? html` - - ` - : nothing} + + + ${this.editMode + ? html` + + ` + : nothing} +
-
- ` - )} - ${this.editMode - ? html` - - - - - - ` - : nothing} -
+ )} + ${this.editMode + ? html` + + + + + + + ` + : nothing} +
+ `; } diff --git a/src/panels/config/automation/action/ha-automation-action.ts b/src/panels/config/automation/action/ha-automation-action.ts index ce312a7bd399..ba1208930788 100644 --- a/src/panels/config/automation/action/ha-automation-action.ts +++ b/src/panels/config/automation/action/ha-automation-action.ts @@ -1,19 +1,16 @@ -import "@material/mwc-button"; import { mdiArrowDown, mdiArrowUp, mdiDrag, mdiPlus } from "@mdi/js"; import deepClone from "deep-clone-simple"; import { CSSResultGroup, LitElement, PropertyValues, css, html } from "lit"; import { customElement, property } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import type { SortableEvent } from "sortablejs"; import { storage } from "../../../../common/decorators/storage"; import { fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/ha-button"; import "../../../../components/ha-svg-icon"; +import "../../../../components/ha-sortable"; import { getService, isService } from "../../../../data/action"; import type { AutomationClipboard } from "../../../../data/automation"; import { Action } from "../../../../data/script"; -import { sortableStyles } from "../../../../resources/ha-sortable-style"; -import type { SortableInstance } from "../../../../resources/sortable"; import { HomeAssistant } from "../../../../types"; import { PASTE_VALUE, @@ -48,8 +45,6 @@ export default class HaAutomationAction extends LitElement { private _actionKeys = new WeakMap(); - private _sortable?: SortableInstance; - protected render() { return html` ${this.reOrderMode && !this.nested @@ -63,62 +58,68 @@ export default class HaAutomationAction extends LitElement { ${this.hass.localize( "ui.panel.config.automation.editor.re_order_mode.description_actions" )} - + ${this.hass.localize( "ui.panel.config.automation.editor.re_order_mode.exit" )} - + ` : null} -
- ${repeat( - this.actions, - (action) => this._getKey(action), - (action, idx) => html` - - ${this.reOrderMode - ? html` - - -
- -
- ` - : ""} -
- ` - )} -
+ +
+ ${repeat( + this.actions, + (action) => this._getKey(action), + (action, idx) => html` + + ${this.reOrderMode + ? html` + + +
+ +
+ ` + : ""} +
+ ` + )} +
+
{ - (evt.item as any).placeholder = - document.createComment("sort-placeholder"); - evt.item.after((evt.item as any).placeholder); - }, - onEnd: (evt: SortableEvent) => { - // put back in original location - if ((evt.item as any).placeholder) { - (evt.item as any).placeholder.replaceWith(evt.item); - delete (evt.item as any).placeholder; - } - this._dragged(evt); - }, - }); - } - - private _destroySortable() { - this._sortable?.destroy(); - this._sortable = undefined; - } - private _getKey(action: Action) { if (!this._actionKeys.has(action)) { this._actionKeys.set(action, Math.random().toString()); @@ -262,11 +229,6 @@ export default class HaAutomationAction extends LitElement { this._move(index, newIndex); } - private _dragged(ev: SortableEvent): void { - if (ev.oldIndex === ev.newIndex) return; - this._move(ev.oldIndex!, ev.newIndex!); - } - private _move(index: number, newIndex: number) { const actions = this.actions.concat(); const action = actions.splice(index, 1)[0]; @@ -274,6 +236,12 @@ export default class HaAutomationAction extends LitElement { fireEvent(this, "value-changed", { value: actions }); } + private _actionMoved(ev: CustomEvent): void { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; + this._move(oldIndex, newIndex); + } + private _actionChanged(ev: CustomEvent) { ev.stopPropagation(); const actions = [...this.actions]; @@ -302,39 +270,36 @@ export default class HaAutomationAction extends LitElement { } static get styles(): CSSResultGroup { - return [ - sortableStyles, - css` - ha-automation-action-row { - display: block; - margin-bottom: 16px; - scroll-margin-top: 48px; - } - ha-svg-icon { - height: 20px; - } - ha-alert { - display: block; - margin-bottom: 16px; - border-radius: var(--ha-card-border-radius, 12px); - overflow: hidden; - } - .handle { - cursor: move; /* fallback if grab cursor is unsupported */ - cursor: grab; - padding: 12px; - } - .handle ha-svg-icon { - pointer-events: none; - height: 24px; - } - .buttons { - display: flex; - flex-wrap: wrap; - gap: 8px; - } - `, - ]; + return css` + ha-automation-action-row { + display: block; + margin-bottom: 16px; + scroll-margin-top: 48px; + } + ha-svg-icon { + height: 20px; + } + ha-alert { + display: block; + margin-bottom: 16px; + border-radius: var(--ha-card-border-radius, 12px); + overflow: hidden; + } + .handle { + padding: 12px; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; + } + .handle ha-svg-icon { + pointer-events: none; + height: 24px; + } + .buttons { + display: flex; + flex-wrap: wrap; + gap: 8px; + } + `; } } diff --git a/src/panels/config/automation/action/types/ha-automation-action-choose.ts b/src/panels/config/automation/action/types/ha-automation-action-choose.ts index 5c0ee0763790..1b4bebb273f2 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-choose.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-choose.ts @@ -1,29 +1,31 @@ import { consume } from "@lit-labs/context"; -import type { SortableEvent } from "sortablejs"; +import type { ActionDetail } from "@material/mwc-list"; import { - mdiDotsVertical, - mdiRenameBox, - mdiSort, + mdiArrowDown, + mdiArrowUp, mdiContentDuplicate, mdiDelete, - mdiPlus, - mdiArrowUp, - mdiArrowDown, + mdiDotsVertical, mdiDrag, + mdiPlus, + mdiRenameBox, + mdiSort, } from "@mdi/js"; import deepClone from "deep-clone-simple"; import { CSSResultGroup, LitElement, PropertyValues, css, html } from "lit"; import { customElement, property, state } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import type { ActionDetail } from "@material/mwc-list"; -import type { SortableInstance } from "../../../../../resources/sortable"; import { ensureArray } from "../../../../../common/array/ensure-array"; import { fireEvent } from "../../../../../common/dom/fire_event"; import { capitalizeFirstLetter } from "../../../../../common/string/capitalize-first-letter"; import "../../../../../components/ha-button"; -import "../../../../../components/ha-icon-button"; import "../../../../../components/ha-button-menu"; +import "../../../../../components/ha-icon-button"; +import "../../../../../components/ha-sortable"; import { Condition } from "../../../../../data/automation"; +import { describeCondition } from "../../../../../data/automation_i18n"; +import { fullEntitiesContext } from "../../../../../data/context"; +import { EntityRegistryEntry } from "../../../../../data/entity_registry"; import { Action, ChooseAction, @@ -36,10 +38,6 @@ import { import { haStyle } from "../../../../../resources/styles"; import { HomeAssistant } from "../../../../../types"; import { ActionElement } from "../ha-automation-action-row"; -import { describeCondition } from "../../../../../data/automation_i18n"; -import { fullEntitiesContext } from "../../../../../data/context"; -import { EntityRegistryEntry } from "../../../../../data/entity_registry"; -import { sortableStyles } from "../../../../../resources/ha-sortable-style"; const preventDefault = (ev) => ev.preventDefault(); @@ -63,8 +61,6 @@ export class HaChooseAction extends LitElement implements ActionElement { private _expandLast = false; - private _sortable?: SortableInstance; - public static get defaultConfig() { return { choose: [{ conditions: [], sequence: [] }] }; } @@ -100,157 +96,166 @@ export class HaChooseAction extends LitElement implements ActionElement { const action = this.action; return html` -
- ${repeat( - action.choose ? ensureArray(action.choose) : [], - (option) => option, - (option, idx) => - html` - -

- ${this.hass.localize( - "ui.panel.config.automation.editor.actions.type.choose.option", - { number: idx + 1 } - )}: - ${option.alias || - (this._expandedStates[idx] - ? "" - : this._getDescription(option))} -

- ${this.reOrderMode - ? html` - - +
+ ${repeat( + action.choose ? ensureArray(action.choose) : [], + (option) => option, + (option, idx) => html` +
+ + +

+ ${this.hass.localize( + "ui.panel.config.automation.editor.actions.type.choose.option", + { number: idx + 1 } + )}: + ${option.alias || + (this._expandedStates[idx] + ? "" + : this._getDescription(option))} +

+ ${this.reOrderMode + ? html` + + +
+ +
+ ` + : html` + + + + ${this.hass.localize( + "ui.panel.config.automation.editor.actions.rename" + )} + + + + ${this.hass.localize( + "ui.panel.config.automation.editor.actions.re_order" + )} + + + + + ${this.hass.localize( + "ui.panel.config.automation.editor.actions.duplicate" + )} + + + + + ${this.hass.localize( + "ui.panel.config.automation.editor.actions.type.choose.remove_option" + )} + + + + `} +
+

+ ${this.hass.localize( + "ui.panel.config.automation.editor.actions.type.choose.conditions" + )}: +

+ ( + option.conditions )} - .path=${mdiArrowDown} - @click=${this._moveDown} - .disabled=${idx === - ensureArray(this.action.choose).length - 1} - > -
- -
- ` - : html` - - - - ${this.hass.localize( - "ui.panel.config.automation.editor.actions.rename" - )} - - - - ${this.hass.localize( - "ui.panel.config.automation.editor.actions.re_order" - )} - - - - - ${this.hass.localize( - "ui.panel.config.automation.editor.actions.duplicate" - )} - - - - - ${this.hass.localize( - "ui.panel.config.automation.editor.actions.type.choose.remove_option" - )} - - - - `} -
-

- ${this.hass.localize( - "ui.panel.config.automation.editor.actions.type.choose.conditions" - )}: -

- ( - option.conditions - )} - .reOrderMode=${this.reOrderMode} - .disabled=${this.disabled} - .hass=${this.hass} - .idx=${idx} - @value-changed=${this._conditionChanged} - > -

- ${this.hass.localize( - "ui.panel.config.automation.editor.actions.type.choose.sequence" - )}: -

- -
- - ` - )} -
+ @value-changed=${this._conditionChanged} + > +

+ ${this.hass.localize( + "ui.panel.config.automation.editor.actions.type.choose.sequence" + )}: +

+ +
+ + +
+ ` + )} +
+ { - (evt.item as any).placeholder = - document.createComment("sort-placeholder"); - evt.item.after((evt.item as any).placeholder); - }, - onEnd: (evt: SortableEvent) => { - // put back in original location - if ((evt.item as any).placeholder) { - (evt.item as any).placeholder.replaceWith(evt.item); - delete (evt.item as any).placeholder; - } - this._dragged(evt); - }, - }); - } - - private _destroySortable() { - this._sortable?.destroy(); - this._sortable = undefined; - } - static get styles(): CSSResultGroup { return [ haStyle, - sortableStyles, css` - ha-card { + .option { margin: 0 0 16px 0; } .add-card mwc-button { @@ -543,9 +512,9 @@ export class HaChooseAction extends LitElement implements ActionElement { padding: 0 16px 16px 16px; } .handle { + padding: 12px; cursor: move; /* fallback if grab cursor is unsupported */ cursor: grab; - padding: 12px; } .handle ha-svg-icon { pointer-events: none; diff --git a/src/panels/config/automation/condition/ha-automation-condition.ts b/src/panels/config/automation/condition/ha-automation-condition.ts index 27364b92a3ed..c240c2ae6cbc 100644 --- a/src/panels/config/automation/condition/ha-automation-condition.ts +++ b/src/panels/config/automation/condition/ha-automation-condition.ts @@ -1,4 +1,3 @@ -import "@material/mwc-button"; import { mdiArrowDown, mdiArrowUp, mdiDrag, mdiPlus } from "@mdi/js"; import deepClone from "deep-clone-simple"; import { @@ -11,18 +10,16 @@ import { } from "lit"; import { customElement, property } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import type { SortableEvent } from "sortablejs"; import { storage } from "../../../../common/decorators/storage"; import { fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/ha-button"; import "../../../../components/ha-button-menu"; +import "../../../../components/ha-sortable"; import "../../../../components/ha-svg-icon"; import type { AutomationClipboard, Condition, } from "../../../../data/automation"; -import { sortableStyles } from "../../../../resources/ha-sortable-style"; -import type { SortableInstance } from "../../../../resources/sortable"; import type { HomeAssistant } from "../../../../types"; import { PASTE_VALUE, @@ -55,17 +52,7 @@ export default class HaAutomationCondition extends LitElement { private _conditionKeys = new WeakMap(); - private _sortable?: SortableInstance; - protected updated(changedProperties: PropertyValues) { - if (changedProperties.has("reOrderMode")) { - if (this.reOrderMode) { - this._createSortable(); - } else { - this._destroySortable(); - } - } - if (!changedProperties.has("conditions")) { return; } @@ -118,63 +105,70 @@ export default class HaAutomationCondition extends LitElement { ${this.hass.localize( "ui.panel.config.automation.editor.re_order_mode.description_conditions" )} - + ${this.hass.localize( "ui.panel.config.automation.editor.re_order_mode.exit" )} - + ` : null} -
- ${repeat( - this.conditions.filter((c) => typeof c === "object"), - (condition) => this._getKey(condition), - (cond, idx) => html` - - ${this.reOrderMode - ? html` - - -
- -
- ` - : ""} -
- ` - )} -
+ + +
+ ${repeat( + this.conditions.filter((c) => typeof c === "object"), + (condition) => this._getKey(condition), + (cond, idx) => html` + + ${this.reOrderMode + ? html` + + +
+ +
+ ` + : ""} +
+ ` + )} +
+
{ - (evt.item as any).placeholder = - document.createComment("sort-placeholder"); - evt.item.after((evt.item as any).placeholder); - }, - onEnd: (evt: SortableEvent) => { - // put back in original location - if ((evt.item as any).placeholder) { - (evt.item as any).placeholder.replaceWith(evt.item); - delete (evt.item as any).placeholder; - } - this._dragged(evt); - }, - } - ); - } - - private _destroySortable() { - this._sortable?.destroy(); - this._sortable = undefined; - } - private _getKey(condition: Condition) { if (!this._conditionKeys.has(condition)) { this._conditionKeys.set(condition, Math.random().toString()); @@ -298,11 +262,6 @@ export default class HaAutomationCondition extends LitElement { this._move(index, newIndex); } - private _dragged(ev: SortableEvent): void { - if (ev.oldIndex === ev.newIndex) return; - this._move(ev.oldIndex!, ev.newIndex!); - } - private _move(index: number, newIndex: number) { const conditions = this.conditions.concat(); const condition = conditions.splice(index, 1)[0]; @@ -310,6 +269,12 @@ export default class HaAutomationCondition extends LitElement { fireEvent(this, "value-changed", { value: conditions }); } + private _conditionMoved(ev: CustomEvent): void { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; + this._move(oldIndex, newIndex); + } + private _conditionChanged(ev: CustomEvent) { ev.stopPropagation(); const conditions = [...this.conditions]; @@ -340,39 +305,36 @@ export default class HaAutomationCondition extends LitElement { } static get styles(): CSSResultGroup { - return [ - sortableStyles, - css` - ha-automation-condition-row { - display: block; - margin-bottom: 16px; - scroll-margin-top: 48px; - } - ha-svg-icon { - height: 20px; - } - ha-alert { - display: block; - margin-bottom: 16px; - border-radius: var(--ha-card-border-radius, 12px); - overflow: hidden; - } - .handle { - cursor: move; /* fallback if grab cursor is unsupported */ - cursor: grab; - padding: 12px; - } - .handle ha-svg-icon { - pointer-events: none; - height: 24px; - } - .buttons { - display: flex; - flex-wrap: wrap; - gap: 8px; - } - `, - ]; + return css` + ha-automation-condition-row { + display: block; + margin-bottom: 16px; + scroll-margin-top: 48px; + } + ha-svg-icon { + height: 20px; + } + ha-alert { + display: block; + margin-bottom: 16px; + border-radius: var(--ha-card-border-radius, 12px); + overflow: hidden; + } + .handle { + padding: 12px; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; + } + .handle ha-svg-icon { + pointer-events: none; + height: 24px; + } + .buttons { + display: flex; + flex-wrap: wrap; + gap: 8px; + } + `; } } diff --git a/src/panels/config/automation/trigger/ha-automation-trigger.ts b/src/panels/config/automation/trigger/ha-automation-trigger.ts index 90467f61e0b8..167a9ab2531a 100644 --- a/src/panels/config/automation/trigger/ha-automation-trigger.ts +++ b/src/panels/config/automation/trigger/ha-automation-trigger.ts @@ -1,25 +1,22 @@ -import "@material/mwc-button"; import { mdiArrowDown, mdiArrowUp, mdiDrag, mdiPlus } from "@mdi/js"; import deepClone from "deep-clone-simple"; import { CSSResultGroup, LitElement, PropertyValues, css, html } from "lit"; import { customElement, property } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import type { SortableEvent } from "sortablejs"; import { storage } from "../../../../common/decorators/storage"; import { fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/ha-button"; import "../../../../components/ha-button-menu"; +import "../../../../components/ha-sortable"; import "../../../../components/ha-svg-icon"; import { AutomationClipboard, Trigger } from "../../../../data/automation"; -import { sortableStyles } from "../../../../resources/ha-sortable-style"; -import type { SortableInstance } from "../../../../resources/sortable"; import { HomeAssistant } from "../../../../types"; -import "./ha-automation-trigger-row"; -import type HaAutomationTriggerRow from "./ha-automation-trigger-row"; import { PASTE_VALUE, showAddAutomationElementDialog, } from "../show-add-automation-element-dialog"; +import "./ha-automation-trigger-row"; +import type HaAutomationTriggerRow from "./ha-automation-trigger-row"; @customElement("ha-automation-trigger") export default class HaAutomationTrigger extends LitElement { @@ -45,8 +42,6 @@ export default class HaAutomationTrigger extends LitElement { private _triggerKeys = new WeakMap(); - private _sortable?: SortableInstance; - protected render() { return html` ${this.reOrderMode && !this.nested @@ -60,70 +55,76 @@ export default class HaAutomationTrigger extends LitElement { ${this.hass.localize( "ui.panel.config.automation.editor.re_order_mode.description_triggers" )} - + ${this.hass.localize( "ui.panel.config.automation.editor.re_order_mode.exit" )} - + ` : null} -
- ${repeat( - this.triggers, - (trigger) => this._getKey(trigger), - (trg, idx) => html` - - ${this.reOrderMode - ? html` - - -
- -
- ` - : ""} -
- ` - )} - +
+ ${repeat( + this.triggers, + (trigger) => this._getKey(trigger), + (trg, idx) => html` + + ${this.reOrderMode + ? html` + + +
+ +
+ ` + : ""} +
+ ` )} - .disabled=${this.disabled} - @click=${this._addTriggerDialog} - > - - -
+
+ + + + `; } @@ -158,14 +159,6 @@ export default class HaAutomationTrigger extends LitElement { protected updated(changedProps: PropertyValues) { super.updated(changedProps); - if (changedProps.has("reOrderMode")) { - if (this.reOrderMode) { - this._createSortable(); - } else { - this._destroySortable(); - } - } - if (changedProps.has("triggers") && this._focusLastTriggerOnChange) { this._focusLastTriggerOnChange = false; @@ -190,36 +183,6 @@ export default class HaAutomationTrigger extends LitElement { this.reOrderMode = false; } - private async _createSortable() { - const Sortable = (await import("../../../../resources/sortable")).default; - this._sortable = new Sortable( - this.shadowRoot!.querySelector(".triggers")!, - { - animation: 150, - fallbackClass: "sortable-fallback", - handle: ".handle", - onChoose: (evt: SortableEvent) => { - (evt.item as any).placeholder = - document.createComment("sort-placeholder"); - evt.item.after((evt.item as any).placeholder); - }, - onEnd: (evt: SortableEvent) => { - // put back in original location - if ((evt.item as any).placeholder) { - (evt.item as any).placeholder.replaceWith(evt.item); - delete (evt.item as any).placeholder; - } - this._dragged(evt); - }, - } - ); - } - - private _destroySortable() { - this._sortable?.destroy(); - this._sortable = undefined; - } - private _getKey(action: Trigger) { if (!this._triggerKeys.has(action)) { this._triggerKeys.set(action, Math.random().toString()); @@ -240,11 +203,6 @@ export default class HaAutomationTrigger extends LitElement { this._move(index, newIndex); } - private _dragged(ev: SortableEvent): void { - if (ev.oldIndex === ev.newIndex) return; - this._move(ev.oldIndex!, ev.newIndex!); - } - private _move(index: number, newIndex: number) { const triggers = this.triggers.concat(); const trigger = triggers.splice(index, 1)[0]; @@ -252,6 +210,12 @@ export default class HaAutomationTrigger extends LitElement { fireEvent(this, "value-changed", { value: triggers }); } + private _triggerMoved(ev: CustomEvent): void { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; + this._move(oldIndex, newIndex); + } + private _triggerChanged(ev: CustomEvent) { ev.stopPropagation(); const triggers = [...this.triggers]; @@ -280,34 +244,31 @@ export default class HaAutomationTrigger extends LitElement { } static get styles(): CSSResultGroup { - return [ - sortableStyles, - css` - ha-automation-trigger-row { - display: block; - margin-bottom: 16px; - scroll-margin-top: 48px; - } - ha-svg-icon { - height: 20px; - } - ha-alert { - display: block; - margin-bottom: 16px; - border-radius: var(--ha-card-border-radius, 16px); - overflow: hidden; - } - .handle { - cursor: move; /* fallback if grab cursor is unsupported */ - cursor: grab; - padding: 12px; - } - .handle ha-svg-icon { - pointer-events: none; - height: 24px; - } - `, - ]; + return css` + ha-automation-trigger-row { + display: block; + margin-bottom: 16px; + scroll-margin-top: 48px; + } + ha-svg-icon { + height: 20px; + } + ha-alert { + display: block; + margin-bottom: 16px; + border-radius: var(--ha-card-border-radius, 16px); + overflow: hidden; + } + .handle { + padding: 12px; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; + } + .handle ha-svg-icon { + pointer-events: none; + height: 24px; + } + `; } } diff --git a/src/panels/config/helpers/forms/ha-input_select-form.ts b/src/panels/config/helpers/forms/ha-input_select-form.ts index e8be0fe50418..69c328f2a0b4 100644 --- a/src/panels/config/helpers/forms/ha-input_select-form.ts +++ b/src/panels/config/helpers/forms/ha-input_select-form.ts @@ -1,22 +1,20 @@ import "@material/mwc-list/mwc-list"; import { mdiDelete, mdiDrag } from "@mdi/js"; -import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import type { SortableEvent } from "sortablejs"; -import { sortableStyles } from "../../../../resources/ha-sortable-style"; import { fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/ha-button"; import "../../../../components/ha-icon-button"; -import "../../../../components/ha-list-item"; import "../../../../components/ha-icon-picker"; +import "../../../../components/ha-list-item"; +import "../../../../components/ha-sortable"; import "../../../../components/ha-textfield"; import type { HaTextField } from "../../../../components/ha-textfield"; import type { InputSelect } from "../../../../data/input_select"; import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box"; import { haStyle } from "../../../../resources/styles"; import type { HomeAssistant } from "../../../../types"; -import type { SortableInstance } from "../../../../resources/sortable"; @customElement("ha-input_select-form") class HaInputSelectForm extends LitElement { @@ -32,59 +30,20 @@ class HaInputSelectForm extends LitElement { @state() private _options: string[] = []; - private _sortable?: SortableInstance; - @query("#option_input", true) private _optionInput?: HaTextField; - public connectedCallback() { - super.connectedCallback(); - this._createSortable(); - } - - public disconnectedCallback() { - super.disconnectedCallback(); - this._destroySortable(); - } - - private async _createSortable() { - const Sortable = (await import("../../../../resources/sortable")).default; - this._sortable = new Sortable(this.shadowRoot!.querySelector(".options")!, { - animation: 150, - fallbackClass: "sortable-fallback", - handle: ".handle", - onChoose: (evt: SortableEvent) => { - (evt.item as any).placeholder = - document.createComment("sort-placeholder"); - evt.item.after((evt.item as any).placeholder); - }, - onEnd: (evt: SortableEvent) => { - // put back in original location - if ((evt.item as any).placeholder) { - (evt.item as any).placeholder.replaceWith(evt.item); - delete (evt.item as any).placeholder; - } - this._dragged(evt); - }, - }); - } - - private _dragged(ev: SortableEvent): void { - if (ev.oldIndex === ev.newIndex) return; - + private _optionMoved(ev: CustomEvent): void { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; const options = this._options.concat(); - const option = options.splice(ev.oldIndex!, 1)[0]; - options.splice(ev.newIndex!, 0, option); + const option = options.splice(oldIndex, 1)[0]; + options.splice(newIndex, 0, option); fireEvent(this, "value-changed", { value: { ...this._item, options }, }); } - private _destroySortable() { - this._sortable?.destroy(); - this._sortable = undefined; - } - set item(item: InputSelect) { this._item = item; if (item) { @@ -142,39 +101,41 @@ class HaInputSelectForm extends LitElement { "ui.dialogs.helper_settings.input_select.options" )}:
- - ${this._options.length - ? repeat( - this._options, - (option) => option, - (option, index) => html` - -
-
- + + + ${this._options.length + ? repeat( + this._options, + (option) => option, + (option, index) => html` + +
+
+ +
+ ${option}
- ${option} -
- + + + ` + ) + : html` + + ${this.hass!.localize( + "ui.dialogs.helper_settings.input_select.no_options" + )} - ` - ) - : html` - - ${this.hass!.localize( - "ui.dialogs.helper_settings.input_select.no_options" - )} - - `} - + `} + +
; - private _sortable?: SortableInstance; - - @query("#unchecked") private _uncheckedContainer?: HTMLElement; - connectedCallback(): void { super.connectedCallback(); if (this.hasUpdated) { @@ -264,9 +258,15 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard { ` : nothing}
- - ${this._renderItems(uncheckedItems, unavailable)} - ` + + + ${this._renderItems(uncheckedItems, unavailable)} + + ` : html`

${this.hass.localize( "ui.panel.lovelace.cards.todo-list.no_unchecked_items" @@ -553,43 +553,12 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard { private async _toggleReorder() { this._reordering = !this._reordering; - await this.updateComplete; - if (this._reordering) { - this._createSortable(); - } else { - this._sortable?.destroy(); - this._sortable = undefined; - } } - private async _createSortable() { - const Sortable = (await import("../../../resources/sortable")).default; - this._sortable = new Sortable(this._uncheckedContainer!, { - animation: 150, - fallbackClass: "sortable-fallback", - dataIdAttr: "item-id", - handle: "ha-svg-icon", - onChoose: (evt: SortableEvent) => { - (evt.item as any).placeholder = - document.createComment("sort-placeholder"); - evt.item.after((evt.item as any).placeholder); - }, - onEnd: (evt: SortableEvent) => { - // put back in original location - if ((evt.item as any).placeholder) { - (evt.item as any).placeholder.replaceWith(evt.item); - delete (evt.item as any).placeholder; - } - if (evt.newIndex === undefined || evt.oldIndex === undefined) { - return; - } - // Since this is `onEnd` event, it's possible that - // an item was dragged away and was put back to its original position. - if (evt.oldIndex !== evt.newIndex) { - this._moveItem(evt.oldIndex, evt.newIndex); - } - }, - }); + private async _itemMoved(ev: CustomEvent) { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; + this._moveItem(oldIndex, newIndex); } private async _moveItem(oldIndex: number, newIndex: number) { @@ -621,165 +590,162 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard { } static get styles(): CSSResultGroup { - return [ - sortableStyles, - css` - ha-card { - height: 100%; - box-sizing: border-box; - } + return css` + ha-card { + height: 100%; + box-sizing: border-box; + } - .has-header { - padding-top: 0; - } + .has-header { + padding-top: 0; + } - .addRow { - padding: 16px; - padding-bottom: 0; - position: relative; - } + .addRow { + padding: 16px; + padding-bottom: 0; + position: relative; + } - .addRow ha-icon-button { - position: absolute; - right: 16px; - inset-inline-start: initial; - inset-inline-end: 16px; - } + .addRow ha-icon-button { + position: absolute; + right: 16px; + inset-inline-start: initial; + inset-inline-end: 16px; + } - .addRow, - .header { - display: flex; - flex-direction: row; - align-items: center; - } + .addRow, + .header { + display: flex; + flex-direction: row; + align-items: center; + } - .header { - padding-left: 30px; - padding-right: 16px; - padding-inline-start: 30px; - padding-inline-end: 16px; - margin-top: 8px; - justify-content: space-between; - direction: var(--direction); - } + .header { + padding-left: 30px; + padding-right: 16px; + padding-inline-start: 30px; + padding-inline-end: 16px; + margin-top: 8px; + justify-content: space-between; + direction: var(--direction); + } - .header span { - color: var(--primary-text-color); - font-weight: 500; - } + .header span { + color: var(--primary-text-color); + font-weight: 500; + } - .empty { - padding: 16px 32px; - } + .empty { + padding: 16px 32px; + } - .item { - margin-top: 8px; - } + .item { + margin-top: 8px; + } - ha-check-list-item { - --mdc-list-item-meta-size: 56px; - min-height: 56px; - height: auto; - } + ha-check-list-item { + --mdc-list-item-meta-size: 56px; + min-height: 56px; + height: auto; + } - ha-check-list-item.multiline { - align-items: flex-start; - --check-list-item-graphic-margin-top: 8px; - } + ha-check-list-item.multiline { + align-items: flex-start; + --check-list-item-graphic-margin-top: 8px; + } - .row { - display: flex; - justify-content: space-between; - } + .row { + display: flex; + justify-content: space-between; + } - .multiline .column { - display: flex; - flex-direction: column; - margin-top: 18px; - margin-bottom: 12px; - } + .multiline .column { + display: flex; + flex-direction: column; + margin-top: 18px; + margin-bottom: 12px; + } - .completed .summary { - text-decoration: line-through; - } + .completed .summary { + text-decoration: line-through; + } - .description, - .due { - font-size: 12px; - color: var(--secondary-text-color); - } + .description, + .due { + font-size: 12px; + color: var(--secondary-text-color); + } - .description { - white-space: initial; - overflow: hidden; - display: -webkit-box; - -webkit-line-clamp: 3; - line-clamp: 3; - -webkit-box-orient: vertical; - } + .description { + white-space: initial; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 3; + line-clamp: 3; + -webkit-box-orient: vertical; + } - .description p { - margin: 0; - } + .description p { + margin: 0; + } - .description a { - color: var(--primary-color); - } + .description a { + color: var(--primary-color); + } - .due { - display: flex; - align-items: center; - } + .due { + display: flex; + align-items: center; + } - .due ha-svg-icon { - margin-right: 4px; - --mdc-icon-size: 14px; - } + .due ha-svg-icon { + margin-right: 4px; + --mdc-icon-size: 14px; + } - .due.overdue { - color: var(--warning-color); - } + .due.overdue { + color: var(--warning-color); + } - .completed .due.overdue { - color: var(--secondary-text-color); - } + .completed .due.overdue { + color: var(--secondary-text-color); + } - .handle { - cursor: move; /* fallback if grab cursor is unsupported */ - cursor: grab; - height: 24px; - padding: 16px 4px; - } + .handle { + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; + height: 24px; + padding: 16px 4px; + } - .deleteItemButton { - position: relative; - left: 8px; - } + .deleteItemButton { + position: relative; + left: 8px; + } - ha-textfield { - flex-grow: 1; - } + ha-textfield { + flex-grow: 1; + } - .divider { - height: 1px; - background-color: var(--divider-color); - margin: 10px 0; - } + .divider { + height: 1px; + background-color: var(--divider-color); + margin: 10px 0; + } - .clearall { - cursor: pointer; - } + .clearall { + cursor: pointer; + } - .todoList { - display: block; - padding: 8px; - } + .todoList { + display: block; + padding: 8px; + } - .warning { - color: var(--error-color); - } - `, - ]; + .warning { + color: var(--error-color); + } + `; } } diff --git a/src/panels/lovelace/components/hui-entity-editor.ts b/src/panels/lovelace/components/hui-entity-editor.ts index 22ac4f8aa08d..0af08f1180f8 100644 --- a/src/panels/lovelace/components/hui-entity-editor.ts +++ b/src/panels/lovelace/components/hui-entity-editor.ts @@ -2,7 +2,6 @@ import { mdiDrag } from "@mdi/js"; import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; import { customElement, property } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import type { SortableEvent } from "sortablejs"; import { fireEvent } from "../../../common/dom/fire_event"; import "../../../components/entity/ha-entity-picker"; import type { @@ -10,8 +9,7 @@ import type { HaEntityPickerEntityFilterFunc, } from "../../../components/entity/ha-entity-picker"; import "../../../components/ha-icon-button"; -import { sortableStyles } from "../../../resources/ha-sortable-style"; -import type { SortableInstance } from "../../../resources/sortable"; +import "../../../components/ha-sortable"; import { HomeAssistant } from "../../../types"; import { EntityConfig } from "../entity-rows/types"; @@ -27,13 +25,6 @@ export class HuiEntityEditor extends LitElement { private _entityKeys = new WeakMap(); - private _sortable?: SortableInstance; - - public disconnectedCallback() { - super.disconnectedCallback(); - this._destroySortable(); - } - private _getKey(action: EntityConfig) { if (!this._entityKeys.has(action)) { this._entityKeys.set(action, Math.random().toString()); @@ -55,27 +46,29 @@ export class HuiEntityEditor extends LitElement { this.hass!.localize("ui.panel.lovelace.editor.card.config.required") + ")"}

-
- ${repeat( - this.entities, - (entityConf) => this._getKey(entityConf), - (entityConf, index) => html` -
-
- + +
+ ${repeat( + this.entities, + (entityConf) => this._getKey(entityConf), + (entityConf, index) => html` +
+
+ +
+
- -
- ` - )} -
+ ` + )} +
+ { - (evt.item as any).placeholder = - document.createComment("sort-placeholder"); - evt.item.after((evt.item as any).placeholder); - }, - onEnd: (evt: SortableEvent) => { - // put back in original location - if ((evt.item as any).placeholder) { - (evt.item as any).placeholder.replaceWith(evt.item); - delete (evt.item as any).placeholder; - } - this._entityMoved(evt); - }, - } - ); - } - - private _destroySortable() { - this._sortable?.destroy(); - this._sortable = undefined; - } - private async _addEntity(ev: CustomEvent): Promise { const value = ev.detail.value; if (value === "") { @@ -132,14 +90,13 @@ export class HuiEntityEditor extends LitElement { fireEvent(this, "entities-changed", { entities: newConfigEntities }); } - private _entityMoved(ev: SortableEvent): void { - if (ev.oldIndex === ev.newIndex) { - return; - } + private _entityMoved(ev: CustomEvent): void { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; const newEntities = this.entities!.concat(); - newEntities.splice(ev.newIndex!, 0, newEntities.splice(ev.oldIndex!, 1)[0]); + newEntities.splice(newIndex, 0, newEntities.splice(oldIndex, 1)[0]); fireEvent(this, "entities-changed", { entities: newEntities }); } @@ -162,39 +119,36 @@ export class HuiEntityEditor extends LitElement { } static get styles(): CSSResultGroup { - return [ - sortableStyles, - css` - ha-entity-picker { - margin-top: 8px; - } - .add-entity { - display: block; - margin-left: 31px; - margin-inline-start: 31px; - margin-inline-end: initial; - direction: var(--direction); - } - .entity { - display: flex; - align-items: center; - } - .entity .handle { - padding-right: 8px; - cursor: move; /* fallback if grab cursor is unsupported */ - cursor: grab; - padding-inline-end: 8px; - padding-inline-start: initial; - direction: var(--direction); - } - .entity .handle > * { - pointer-events: none; - } - .entity ha-entity-picker { - flex-grow: 1; - } - `, - ]; + return css` + ha-entity-picker { + margin-top: 8px; + } + .add-entity { + display: block; + margin-left: 31px; + margin-inline-start: 31px; + margin-inline-end: initial; + direction: var(--direction); + } + .entity { + display: flex; + align-items: center; + } + .entity .handle { + padding-right: 8px; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; + padding-inline-end: 8px; + padding-inline-start: initial; + direction: var(--direction); + } + .entity .handle > * { + pointer-events: none; + } + .entity ha-entity-picker { + flex-grow: 1; + } + `; } } diff --git a/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts b/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts index 8693be890d8d..d8fe23d0a7c9 100644 --- a/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts @@ -3,13 +3,13 @@ import { HassEntity } from "home-assistant-js-websocket"; import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import { customElement, property } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import type { SortableEvent } from "sortablejs"; import { fireEvent } from "../../../../common/dom/fire_event"; import { stopPropagation } from "../../../../common/dom/stop_propagation"; import "../../../../components/entity/ha-entity-picker"; import "../../../../components/ha-button"; import "../../../../components/ha-icon-button"; import "../../../../components/ha-list-item"; +import "../../../../components/ha-sortable"; import "../../../../components/ha-svg-icon"; import { CUSTOM_TYPE_PREFIX, @@ -18,8 +18,6 @@ import { isCustomType, stripCustomPrefix, } from "../../../../data/lovelace_custom_cards"; -import { sortableStyles } from "../../../../resources/ha-sortable-style"; -import type { SortableInstance } from "../../../../resources/sortable"; import { HomeAssistant } from "../../../../types"; import { supportsAlarmModesCardFeature } from "../../card-features/hui-alarm-modes-card-feature"; import { supportsClimateFanModesCardFeature } from "../../card-features/hui-climate-fan-modes-card-feature"; @@ -39,11 +37,11 @@ import { supportsNumericInputCardFeature } from "../../card-features/hui-numeric import { supportsSelectOptionsCardFeature } from "../../card-features/hui-select-options-card-feature"; import { supportsTargetHumidityCardFeature } from "../../card-features/hui-target-humidity-card-feature"; import { supportsTargetTemperatureCardFeature } from "../../card-features/hui-target-temperature-card-feature"; +import { supportsUpdateActionsCardFeature } from "../../card-features/hui-update-actions-card-feature"; import { supportsVacuumCommandsCardFeature } from "../../card-features/hui-vacuum-commands-card-feature"; import { supportsWaterHeaterOperationModesCardFeature } from "../../card-features/hui-water-heater-operation-modes-card-feature"; import { LovelaceCardFeatureConfig } from "../../card-features/types"; import { getCardFeatureElementClass } from "../../create-element/create-card-feature-element"; -import { supportsUpdateActionsCardFeature } from "../../card-features/hui-update-actions-card-feature"; export type FeatureType = LovelaceCardFeatureConfig["type"]; type SupportsFeature = (stateObj: HassEntity) => boolean; @@ -149,13 +147,6 @@ export class HuiCardFeaturesEditor extends LitElement { private _featuresKeys = new WeakMap(); - private _sortable?: SortableInstance; - - public disconnectedCallback() { - super.disconnectedCallback(); - this._destroySortable(); - } - private _supportsFeatureType(type: string): boolean { if (!this.stateObj) return false; @@ -205,10 +196,6 @@ export class HuiCardFeaturesEditor extends LitElement { return this._featuresKeys.get(feature)!; } - protected firstUpdated() { - this._createSortable(); - } - private _getSupportedFeaturesType() { const featuresTypes = UI_FEATURE_TYPES.filter( (type) => !this.featuresTypes || this.featuresTypes.includes(type) @@ -249,61 +236,66 @@ export class HuiCardFeaturesEditor extends LitElement { ` : nothing} -
- ${repeat( - this.features, - (featureConf) => this._getKey(featureConf), - (featureConf, index) => { - const type = featureConf.type; - const supported = this._supportsFeatureType(type); - const editable = this._isFeatureTypeEditable(type); - return html` -
-
- -
-
-
- ${this._getFeatureTypeLabel(type)} - ${this.stateObj && !supported - ? html` - - ${this.hass!.localize( - "ui.panel.lovelace.editor.features.not_compatible" - )} - - ` - : nothing} + +
+ ${repeat( + this.features, + (featureConf) => this._getKey(featureConf), + (featureConf, index) => { + const type = featureConf.type; + const supported = this._supportsFeatureType(type); + const editable = this._isFeatureTypeEditable(type); + return html` +
+
+ +
+
+
+ ${this._getFeatureTypeLabel(type)} + ${this.stateObj && !supported + ? html` + + ${this.hass!.localize( + "ui.panel.lovelace.editor.features.not_compatible" + )} + + ` + : nothing} +
+ ${editable + ? html` + + ` + : nothing} +
- ${editable - ? html` - - ` - : nothing} - -
- `; - } - )} -
+ `; + } + )} +
+ ${supportedFeaturesType.length > 0 ? html` { - (evt.item as any).placeholder = - document.createComment("sort-placeholder"); - evt.item.after((evt.item as any).placeholder); - }, - onEnd: (evt: SortableEvent) => { - // put back in original location - if ((evt.item as any).placeholder) { - (evt.item as any).placeholder.replaceWith(evt.item); - delete (evt.item as any).placeholder; - } - this._rowMoved(evt); - }, - } - ); - } - - private _destroySortable() { - this._sortable?.destroy(); - this._sortable = undefined; - } - private async _addFeature(ev: CustomEvent): Promise { const index = ev.detail.index as number; @@ -395,14 +357,13 @@ export class HuiCardFeaturesEditor extends LitElement { fireEvent(this, "features-changed", { features: newConfigFeature }); } - private _rowMoved(ev: SortableEvent): void { - if (ev.oldIndex === ev.newIndex) { - return; - } + private _featureMoved(ev: CustomEvent): void { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; const newFeatures = this.features!.concat(); - newFeatures.splice(ev.newIndex!, 0, newFeatures.splice(ev.oldIndex!, 1)[0]); + newFeatures.splice(newIndex, 0, newFeatures.splice(oldIndex, 1)[0]); fireEvent(this, "features-changed", { features: newFeatures }); } @@ -428,79 +389,76 @@ export class HuiCardFeaturesEditor extends LitElement { } static get styles(): CSSResultGroup { - return [ - sortableStyles, - css` - :host { - display: flex !important; - flex-direction: column; - } - .content { - padding: 12px; - } - ha-expansion-panel { - display: block; - --expansion-panel-content-padding: 0; - border-radius: 6px; - } - h3 { - margin: 0; - font-size: inherit; - font-weight: inherit; - } - ha-svg-icon, - ha-icon { - color: var(--secondary-text-color); - } - ha-button-menu { - margin-top: 8px; - } - .feature { - display: flex; - align-items: center; - } - .feature .handle { - padding-right: 8px; - cursor: move; /* fallback if grab cursor is unsupported */ - cursor: grab; - padding-inline-end: 8px; - padding-inline-start: initial; - direction: var(--direction); - } - .feature .handle > * { - pointer-events: none; - } - - .feature-content { - height: 60px; - font-size: 16px; - display: flex; - align-items: center; - justify-content: space-between; - flex-grow: 1; - } - - .feature-content div { - display: flex; - flex-direction: column; - } - - .remove-icon, - .edit-icon { - --mdc-icon-button-size: 36px; - color: var(--secondary-text-color); - } - - .secondary { - font-size: 12px; - color: var(--secondary-text-color); - } - - li[divider] { - border-bottom-color: var(--divider-color); - } - `, - ]; + return css` + :host { + display: flex !important; + flex-direction: column; + } + .content { + padding: 12px; + } + ha-expansion-panel { + display: block; + --expansion-panel-content-padding: 0; + border-radius: 6px; + } + h3 { + margin: 0; + font-size: inherit; + font-weight: inherit; + } + ha-svg-icon, + ha-icon { + color: var(--secondary-text-color); + } + ha-button-menu { + margin-top: 8px; + } + .feature { + display: flex; + align-items: center; + } + .feature .handle { + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; + padding-right: 8px; + padding-inline-end: 8px; + padding-inline-start: initial; + direction: var(--direction); + } + .feature .handle > * { + pointer-events: none; + } + + .feature-content { + height: 60px; + font-size: 16px; + display: flex; + align-items: center; + justify-content: space-between; + flex-grow: 1; + } + + .feature-content div { + display: flex; + flex-direction: column; + } + + .remove-icon, + .edit-icon { + --mdc-icon-button-size: 36px; + color: var(--secondary-text-color); + } + + .secondary { + font-size: 12px; + color: var(--secondary-text-color); + } + + li[divider] { + border-bottom-color: var(--divider-color); + } + `; } } diff --git a/src/panels/lovelace/editor/hui-entities-card-row-editor.ts b/src/panels/lovelace/editor/hui-entities-card-row-editor.ts index 231305a1a3aa..58891055fc8c 100644 --- a/src/panels/lovelace/editor/hui-entities-card-row-editor.ts +++ b/src/panels/lovelace/editor/hui-entities-card-row-editor.ts @@ -1,15 +1,13 @@ import { mdiClose, mdiDrag, mdiPencil } from "@mdi/js"; -import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import { customElement, property } from "lit/decorators"; import { repeat } from "lit/directives/repeat"; -import type { SortableEvent } from "sortablejs"; import { fireEvent } from "../../../common/dom/fire_event"; import "../../../components/entity/ha-entity-picker"; import type { HaEntityPicker } from "../../../components/entity/ha-entity-picker"; import "../../../components/ha-icon-button"; +import "../../../components/ha-sortable"; import "../../../components/ha-svg-icon"; -import { sortableStyles } from "../../../resources/ha-sortable-style"; -import type { SortableInstance } from "../../../resources/sortable"; import { HomeAssistant } from "../../../types"; import { EntityConfig, LovelaceRowConfig } from "../entity-rows/types"; @@ -31,13 +29,6 @@ export class HuiEntitiesCardRowEditor extends LitElement { private _entityKeys = new WeakMap(); - private _sortable?: SortableInstance; - - public disconnectedCallback() { - super.disconnectedCallback(); - this._destroySortable(); - } - private _getKey(action: LovelaceRowConfig) { if (!this._entityKeys.has(action)) { this._entityKeys.set(action, Math.random().toString()); @@ -60,64 +51,66 @@ export class HuiEntitiesCardRowEditor extends LitElement { "ui.panel.lovelace.editor.card.config.required" )})`} -
- ${repeat( - this.entities, - (entityConf) => this._getKey(entityConf), - (entityConf, index) => html` -
-
- -
- ${entityConf.type - ? html` -
-
- - ${this.hass!.localize( - `ui.panel.lovelace.editor.card.entities.entity_row.${entityConf.type}` - )} - - ${this.hass!.localize( - "ui.panel.lovelace.editor.card.entities.edit_special_row" - )} + +
+ ${repeat( + this.entities, + (entityConf) => this._getKey(entityConf), + (entityConf, index) => html` +
+
+ +
+ ${entityConf.type + ? html` +
+
+ + ${this.hass!.localize( + `ui.panel.lovelace.editor.card.entities.entity_row.${entityConf.type}` + )} + + ${this.hass!.localize( + "ui.panel.lovelace.editor.card.entities.edit_special_row" + )} +
-
- ` - : html` - - `} - - -
- ` - )} -
+ ` + : html` + + `} + + +
+ ` + )} +
+ { - (evt.item as any).placeholder = - document.createComment("sort-placeholder"); - evt.item.after((evt.item as any).placeholder); - }, - onEnd: (evt: SortableEvent) => { - // put back in original location - if ((evt.item as any).placeholder) { - (evt.item as any).placeholder.replaceWith(evt.item); - delete (evt.item as any).placeholder; - } - this._rowMoved(evt); - }, - } - ); - } - - private _destroySortable() { - this._sortable?.destroy(); - this._sortable = undefined; - } - private async _addEntity(ev: CustomEvent): Promise { const value = ev.detail.value; if (value === "") { @@ -172,14 +131,13 @@ export class HuiEntitiesCardRowEditor extends LitElement { fireEvent(this, "entities-changed", { entities: newConfigEntities }); } - private _rowMoved(ev: SortableEvent): void { - if (ev.oldIndex === ev.newIndex) { - return; - } + private _rowMoved(ev: CustomEvent): void { + ev.stopPropagation(); + const { oldIndex, newIndex } = ev.detail; const newEntities = this.entities!.concat(); - newEntities.splice(ev.newIndex!, 0, newEntities.splice(ev.oldIndex!, 1)[0]); + newEntities.splice(newIndex, 0, newEntities.splice(oldIndex, 1)[0]); fireEvent(this, "entities-changed", { entities: newEntities }); } @@ -222,67 +180,64 @@ export class HuiEntitiesCardRowEditor extends LitElement { } static get styles(): CSSResultGroup { - return [ - sortableStyles, - css` - ha-entity-picker { - margin-top: 8px; - } - .add-entity { - display: block; - margin-left: 31px; - margin-right: 71px; - margin-inline-start: 31px; - margin-inline-end: 71px; - direction: var(--direction); - } - .entity { - display: flex; - align-items: center; - } + return css` + ha-entity-picker { + margin-top: 8px; + } + .add-entity { + display: block; + margin-left: 31px; + margin-right: 71px; + margin-inline-start: 31px; + margin-inline-end: 71px; + direction: var(--direction); + } + .entity { + display: flex; + align-items: center; + } - .entity .handle { - padding-right: 8px; - cursor: move; /* fallback if grab cursor is unsupported */ - cursor: grab; - padding-inline-end: 8px; - padding-inline-start: initial; - direction: var(--direction); - } - .entity .handle > * { - pointer-events: none; - } + .entity .handle { + padding-right: 8px; + cursor: move; /* fallback if grab cursor is unsupported */ + cursor: grab; + padding-inline-end: 8px; + padding-inline-start: initial; + direction: var(--direction); + } + .entity .handle > * { + pointer-events: none; + } - .entity ha-entity-picker { - flex-grow: 1; - } + .entity ha-entity-picker { + flex-grow: 1; + } - .special-row { - height: 60px; - font-size: 16px; - display: flex; - align-items: center; - justify-content: space-between; - flex-grow: 1; - } + .special-row { + height: 60px; + font-size: 16px; + display: flex; + align-items: center; + justify-content: space-between; + flex-grow: 1; + } - .special-row div { - display: flex; - flex-direction: column; - } + .special-row div { + display: flex; + flex-direction: column; + } - .remove-icon, - .edit-icon { - --mdc-icon-button-size: 36px; - color: var(--secondary-text-color); - } + .remove-icon, + .edit-icon { + --mdc-icon-button-size: 36px; + color: var(--secondary-text-color); + } - .secondary { - font-size: 12px; - color: var(--secondary-text-color); - } - `, - ]; + .secondary { + font-size: 12px; + color: var(--secondary-text-color); + } + `; } } diff --git a/src/resources/ha-sortable-style.ts b/src/resources/ha-sidebar-edit-style.ts similarity index 74% rename from src/resources/ha-sortable-style.ts rename to src/resources/ha-sidebar-edit-style.ts index a1fcfe920900..50bf37c75616 100644 --- a/src/resources/ha-sortable-style.ts +++ b/src/resources/ha-sidebar-edit-style.ts @@ -1,7 +1,7 @@ import { css } from "lit"; -export const sortableStyles = css` - #sortable a:nth-of-type(2n) paper-icon-item { +export const sidebarEditStyle = css` + .reorder-list a:nth-of-type(2n) paper-icon-item { animation-name: keyframes1; animation-iteration-count: infinite; transform-origin: 50% 10%; @@ -9,7 +9,7 @@ export const sortableStyles = css` animation-duration: 0.25s; } - #sortable a:nth-of-type(2n-1) paper-icon-item { + .reorder-list a:nth-of-type(2n-1) paper-icon-item { animation-name: keyframes2; animation-iteration-count: infinite; animation-direction: alternate; @@ -18,12 +18,12 @@ export const sortableStyles = css` animation-duration: 0.33s; } - #sortable a { + .reorder-list a { height: 48px; display: flex; } - #sortable { + .reorder-list { outline: none; display: block !important; } @@ -32,26 +32,6 @@ export const sortableStyles = css` display: flex !important; } - .sortable-fallback { - display: none; - opacity: 0; - } - - .sortable-ghost { - border: 2px solid var(--primary-color); - background: rgba(var(--rgb-primary-color), 0.25); - border-radius: 4px; - opacity: 0.4; - } - - .sortable-drag { - border-radius: 4px; - opacity: 1; - background: var(--card-background-color); - box-shadow: 0px 4px 8px 3px #00000026; - cursor: grabbing; - } - @keyframes keyframes1 { 0% { transform: rotate(-1deg); From ae79df8c55c174e900a38669730eedf9e20bba60 Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Mon, 8 Jan 2024 08:07:08 -0500 Subject: [PATCH 096/361] Allow TLA for legacy build and remove static Intl polyfills (#19207) --- build-scripts/webpack.cjs | 16 +++++----------- package.json | 1 + src/resources/intl-polyfill-legacy.ts | 19 ------------------- yarn.lock | 17 +++++++++++++++-- 4 files changed, 21 insertions(+), 32 deletions(-) delete mode 100644 src/resources/intl-polyfill-legacy.ts diff --git a/build-scripts/webpack.cjs b/build-scripts/webpack.cjs index 432cca35d2ca..e1047cadd4ba 100644 --- a/build-scripts/webpack.cjs +++ b/build-scripts/webpack.cjs @@ -7,6 +7,9 @@ const TerserPlugin = require("terser-webpack-plugin"); const { WebpackManifestPlugin } = require("webpack-manifest-plugin"); const log = require("fancy-log"); const WebpackBar = require("webpackbar"); +const { + TransformAsyncModulesPlugin, +} = require("transform-async-modules-webpack-plugin"); const paths = require("./paths.cjs"); const bundle = require("./bundle.cjs"); @@ -142,17 +145,6 @@ const createWebpackConfig = ({ ), path.resolve(paths.polymer_dir, "src/util/empty.js") ), - // See `src/resources/intl-polyfill-legacy.ts` for explanation - !latestBuild && - new webpack.NormalModuleReplacementPlugin( - new RegExp( - path.resolve(paths.polymer_dir, "src/resources/intl-polyfill.ts") - ), - path.resolve( - paths.polymer_dir, - "src/resources/intl-polyfill-legacy.ts" - ) - ), !isProdBuild && new LogStartCompilePlugin(), isProdBuild && new StatsWriterPlugin({ @@ -163,6 +155,8 @@ const createWebpackConfig = ({ stats: { assets: true, chunks: true, modules: true }, transform: (stats) => JSON.stringify(filterStats(stats)), }), + !latestBuild && + new TransformAsyncModulesPlugin({ browserslistEnv: "legacy" }), ].filter(Boolean), resolve: { extensions: [".ts", ".js", ".json"], diff --git a/package.json b/package.json index 0c7a6998ca19..818fa25fa128 100644 --- a/package.json +++ b/package.json @@ -235,6 +235,7 @@ "systemjs": "6.14.3", "tar": "6.2.0", "terser-webpack-plugin": "5.3.10", + "transform-async-modules-webpack-plugin": "1.0.2", "ts-lit-plugin": "2.0.1", "typescript": "5.3.3", "vinyl-buffer": "1.0.1", diff --git a/src/resources/intl-polyfill-legacy.ts b/src/resources/intl-polyfill-legacy.ts deleted file mode 100644 index 01a057d75a9b..000000000000 --- a/src/resources/intl-polyfill-legacy.ts +++ /dev/null @@ -1,19 +0,0 @@ -// This module is a simpler version of `intl-polyfill` without top level await, and replaces it for legacy builds. -// Babel cannot transform TLA, and Webpack uses an async function to support it, -// so builds with browser targets without async support will be broken. - -import "@formatjs/intl-getcanonicallocales/polyfill"; -import "@formatjs/intl-locale/polyfill"; -import "@formatjs/intl-pluralrules/polyfill"; -import "@formatjs/intl-pluralrules/locale-data/en"; -import "@formatjs/intl-numberformat/polyfill"; -import "@formatjs/intl-numberformat/locale-data/en"; -import "@formatjs/intl-relativetimeformat/polyfill"; -import "@formatjs/intl-relativetimeformat/locale-data/en"; -import "@formatjs/intl-datetimeformat/polyfill"; -import "@formatjs/intl-datetimeformat/locale-data/en"; -import "@formatjs/intl-datetimeformat/add-all-tz"; -import "@formatjs/intl-displaynames/polyfill"; -import "@formatjs/intl-displaynames/locale-data/en"; -import "@formatjs/intl-listformat/polyfill"; -import "@formatjs/intl-listformat/locale-data/en"; diff --git a/yarn.lock b/yarn.lock index ef48030ab766..70e9ccb6e016 100644 --- a/yarn.lock +++ b/yarn.lock @@ -62,7 +62,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:7.23.7, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3": +"@babel/core@npm:7.23.7, @babel/core@npm:^7.0.0, @babel/core@npm:^7.11.1, @babel/core@npm:^7.12.3": version: 7.23.7 resolution: "@babel/core@npm:7.23.7" dependencies: @@ -1267,7 +1267,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-env@npm:7.23.7, @babel/preset-env@npm:^7.11.0": +"@babel/preset-env@npm:7.23.7, @babel/preset-env@npm:^7.0.0, @babel/preset-env@npm:^7.11.0": version: 7.23.7 resolution: "@babel/preset-env@npm:7.23.7" dependencies: @@ -9665,6 +9665,7 @@ __metadata: tar: "npm:6.2.0" terser-webpack-plugin: "npm:5.3.10" tinykeys: "npm:2.1.0" + transform-async-modules-webpack-plugin: "npm:1.0.2" ts-lit-plugin: "npm:2.0.1" tsparticles-engine: "npm:2.12.0" tsparticles-preset-links: "npm:2.12.0" @@ -15201,6 +15202,18 @@ __metadata: languageName: node linkType: hard +"transform-async-modules-webpack-plugin@npm:1.0.2": + version: 1.0.2 + resolution: "transform-async-modules-webpack-plugin@npm:1.0.2" + dependencies: + "@babel/core": "npm:^7.0.0" + "@babel/preset-env": "npm:^7.0.0" + peerDependencies: + webpack: ^5.0.0 + checksum: 645df77c31e42f8ae57d86dfa023f67e4a3854f3b0848a9fd28392cb83d91fc05762150b909d01ad570e867b9e16e7e49c88a183d2dc7911d0e0154aaac21d52 + languageName: node + linkType: hard + "ts-api-utils@npm:^1.0.1": version: 1.0.3 resolution: "ts-api-utils@npm:1.0.3" From f5fc66f47eeb1eef9f9056e1a39612e9636019a6 Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Mon, 8 Jan 2024 08:08:21 -0500 Subject: [PATCH 097/361] Better restrict applying dependencies label (#19319) --- .github/labeler.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index b09de205bac6..bc82f5f31a3e 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -25,13 +25,18 @@ Design: Dependencies: - changed-files: - - any-glob-to-any-file: + # Match when only these files are changed (i.e. don't match PRs that happen to add or remove packages) + - any-glob-to-all-files: - package.json - renovate.json - yarn.lock - .yarn/** - .yarnrc.yml - .nvmrc + # Dependabot and Renovate branches always match (i.e. compatibility tweaks by members considered minor) + - head-branch: + - "^renovate/" + - "^dependabot/" GitHub Actions: - changed-files: From ec2ae15e3fa890c47c1e4042eb8d1b820694cde2 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Mon, 8 Jan 2024 05:10:23 -0800 Subject: [PATCH 098/361] Cleanup else/default block when deleting all actions (#19298) --- .../types/ha-automation-action-choose.ts | 17 ++++++++++------- .../action/types/ha-automation-action-if.ts | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/panels/config/automation/action/types/ha-automation-action-choose.ts b/src/panels/config/automation/action/types/ha-automation-action-choose.ts index 1b4bebb273f2..5add402d207c 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-choose.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-choose.ts @@ -468,13 +468,16 @@ export class HaChooseAction extends LitElement implements ActionElement { private _defaultChanged(ev: CustomEvent) { ev.stopPropagation(); - const value = ev.detail.value as Action[]; - fireEvent(this, "value-changed", { - value: { - ...this.action, - default: value, - }, - }); + this._showDefault = true; + const defaultAction = ev.detail.value as Action[]; + const newValue: ChooseAction = { + ...this.action, + default: defaultAction, + }; + if (defaultAction.length === 0) { + delete newValue.default; + } + fireEvent(this, "value-changed", { value: newValue }); } static get styles(): CSSResultGroup { diff --git a/src/panels/config/automation/action/types/ha-automation-action-if.ts b/src/panels/config/automation/action/types/ha-automation-action-if.ts index 195590a6892b..a14fe2725d4c 100644 --- a/src/panels/config/automation/action/types/ha-automation-action-if.ts +++ b/src/panels/config/automation/action/types/ha-automation-action-if.ts @@ -117,14 +117,16 @@ export class HaIfAction extends LitElement implements ActionElement { private _elseChanged(ev: CustomEvent) { ev.stopPropagation(); - const value = ev.detail.value as Action[]; - - fireEvent(this, "value-changed", { - value: { - ...this.action, - else: value, - }, - }); + this._showElse = true; + const elseAction = ev.detail.value as Action[]; + const newValue: IfAction = { + ...this.action, + else: elseAction, + }; + if (elseAction.length === 0) { + delete newValue.else; + } + fireEvent(this, "value-changed", { value: newValue }); } static get styles(): CSSResultGroup { From e0f578c135eab685c8c587e48c927e3c09277f2b Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Mon, 8 Jan 2024 08:26:25 -0500 Subject: [PATCH 099/361] Start linting with lit-analyzer (#19302) --- .github/workflows/ci.yaml | 2 ++ lint-staged.config.js | 1 + package.json | 4 ++-- tsconfig.json | 24 +++++++++++++++++------- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index af8a33890396..85f34c02887d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -48,6 +48,8 @@ jobs: run: yarn run lint:eslint --quiet - name: Run tsc run: yarn run lint:types + - name: Run lit-analyzer + run: yarn run lint:lit --quiet - name: Run prettier run: yarn run lint:prettier test: diff --git a/lint-staged.config.js b/lint-staged.config.js index 8740aaab198a..5359a96eee05 100644 --- a/lint-staged.config.js +++ b/lint-staged.config.js @@ -2,6 +2,7 @@ export default { "*.?(c|m){js,ts}": [ "eslint --cache --cache-strategy=content --cache-location=node_modules/.cache/eslint/.eslintcache --fix", "prettier --cache --write", + "lit-analyzer", ], "*.{json,css,md,markdown,html,y?aml}": "prettier --cache --write", "translations/*/*.json": (files) => diff --git a/package.json b/package.json index 818fa25fa128..b591fab97d7c 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ "lint:prettier": "prettier . --cache --check", "format:prettier": "prettier . --cache --write", "lint:types": "tsc", - "lint:lit": "lit-analyzer \"**/src/**/*.ts\" --format markdown --outFile result.md", - "lint": "yarn run lint:eslint && yarn run lint:prettier && yarn run lint:types", + "lint:lit": "lit-analyzer \"{.,*}/src/**/*.ts\"", + "lint": "yarn run lint:eslint && yarn run lint:prettier && yarn run lint:types && yarn run lint:lit", "format": "yarn run format:eslint && yarn run format:prettier", "postinstall": "husky install", "prepack": "pinst --disable", diff --git a/tsconfig.json b/tsconfig.json index a5bac525d4b4..0a45a72573b1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,15 +25,25 @@ "plugins": [ { "name": "ts-lit-plugin", - "strict": false, + "strict": true, "rules": { - "no-unknown-tag-name": "error", - "no-missing-import": "error", - "no-unclosed-tag": "error", - "no-incompatible-type-binding": "warning", - "no-invalid-css": "warning", + // Custom elements + "no-unclosed-tag": "warning", "no-missing-element-type-definition": "warning", - "no-property-visibility-mismatch": "error" + // Binding names + "no-legacy-attribute": "error", + // Binding types + "no-boolean-in-attribute-binding": "warning", + "no-expressionless-property-binding": "warning", + "no-complex-attribute-binding": "warning", + "no-nullable-attribute-binding": "warning", + "no-incompatible-type-binding": "warning", + "no-invalid-directive-binding": "warning", + // LitElement + "no-incompatible-property-type": "warning", + "no-property-visibility-mismatch": "warning", + // CSS + "no-invalid-css": "off" // warning does not work } } ] From 3b6b77c75b8f7d69076712559454e63a6e773fdd Mon Sep 17 00:00:00 2001 From: Simon Lamon <32477463+silamon@users.noreply.github.com> Date: Mon, 8 Jan 2024 15:24:37 +0100 Subject: [PATCH 100/361] Localize time pattern trigger in automation editor (#19173) --- src/data/automation_i18n.ts | 136 ++++++++++++++++++++++++------------ src/translations/en.json | 6 +- 2 files changed, 98 insertions(+), 44 deletions(-) diff --git a/src/data/automation_i18n.ts b/src/data/automation_i18n.ts index aec2965cdf10..d7f186a0dc3b 100644 --- a/src/data/automation_i18n.ts +++ b/src/data/automation_i18n.ts @@ -64,23 +64,6 @@ const localizeTimeString = ( } }; -const ordinalSuffix = (n: number) => { - n %= 100; - if ([11, 12, 13].includes(n)) { - return "th"; - } - if (n % 10 === 1) { - return "st"; - } - if (n % 10 === 2) { - return "nd"; - } - if (n % 10 === 3) { - return "rd"; - } - return "th"; -}; - export const describeTrigger = ( trigger: Trigger, hass: HomeAssistant, @@ -401,14 +384,37 @@ const tryDescribeTrigger = ( // Time Pattern Trigger if (trigger.platform === "time_pattern") { if (!trigger.seconds && !trigger.minutes && !trigger.hours) { - return "When a time pattern matches"; + return hass.localize( + `${triggerTranslationBaseKey}.time_pattern.description.initial` + ); } - let result = "Trigger "; + + const invalidParts: Array<"seconds" | "minutes" | "hours"> = []; + + let secondsChoice: "every" | "every_interval" | "on_the_xth" | "other" = + "other"; + let minutesChoice: + | "every" + | "every_interval" + | "on_the_xth" + | "other" + | "has_seconds" = "other"; + let hoursChoice: + | "every" + | "every_interval" + | "on_the_xth" + | "other" + | "has_seconds_or_minutes" = "other"; + + let seconds = 0; + let minutes = 0; + let hours = 0; + if (trigger.seconds !== undefined) { const seconds_all = trigger.seconds === "*"; const seconds_interval = typeof trigger.seconds === "string" && trigger.seconds.startsWith("/"); - const seconds = seconds_all + seconds = seconds_all ? 0 : typeof trigger.seconds === "number" ? trigger.seconds @@ -422,22 +428,22 @@ const tryDescribeTrigger = ( seconds < 0 || (seconds_interval && seconds === 0) ) { - return "Invalid Time Pattern Seconds"; + invalidParts.push("seconds"); } if (seconds_all || (seconds_interval && seconds === 1)) { - result += "every second of "; + secondsChoice = "every"; } else if (seconds_interval) { - result += `every ${seconds} seconds of `; + secondsChoice = "every_interval"; } else { - result += `on the ${seconds}${ordinalSuffix(seconds)} second of `; + secondsChoice = "on_the_xth"; } } if (trigger.minutes !== undefined) { const minutes_all = trigger.minutes === "*"; const minutes_interval = typeof trigger.minutes === "string" && trigger.minutes.startsWith("/"); - const minutes = minutes_all + minutes = minutes_all ? 0 : typeof trigger.minutes === "number" ? trigger.minutes @@ -451,30 +457,30 @@ const tryDescribeTrigger = ( minutes < 0 || (minutes_interval && minutes === 0) ) { - return "Invalid Time Pattern Minutes"; + invalidParts.push("minutes"); } if (minutes_all || (minutes_interval && minutes === 1)) { - result += "every minute of "; + minutesChoice = "every"; } else if (minutes_interval) { - result += `every ${minutes} minutes of `; + minutesChoice = "every_interval"; } else { - result += `${ - trigger.seconds !== undefined ? "" : "on" - } the ${minutes}${ordinalSuffix(minutes)} minute of `; + minutesChoice = + trigger.seconds !== undefined ? "has_seconds" : "on_the_xth"; } } else if (trigger.seconds !== undefined) { if (trigger.hours !== undefined) { - result += `the 0${ordinalSuffix(0)} minute of `; + minutes = 0; + minutesChoice = "has_seconds"; } else { - result += "every minute of "; + minutesChoice = "every"; } } if (trigger.hours !== undefined) { const hours_all = trigger.hours === "*"; const hours_interval = typeof trigger.hours === "string" && trigger.hours.startsWith("/"); - const hours = hours_all + hours = hours_all ? 0 : typeof trigger.hours === "number" ? trigger.hours @@ -488,24 +494,68 @@ const tryDescribeTrigger = ( hours < 0 || (hours_interval && hours === 0) ) { - return "Invalid Time Pattern Hours"; + invalidParts.push("hours"); } if (hours_all || (hours_interval && hours === 1)) { - result += "every hour"; + hoursChoice = "every"; } else if (hours_interval) { - result += `every ${hours} hours`; + hoursChoice = "every_interval"; } else { - result += `${ + hoursChoice = trigger.seconds !== undefined || trigger.minutes !== undefined - ? "" - : "on" - } the ${hours}${ordinalSuffix(hours)} hour`; + ? "has_seconds_or_minutes" + : "on_the_xth"; } } else { - result += "every hour"; + hoursChoice = "every"; } - return result; + + if (invalidParts.length !== 0) { + return hass.localize( + `${triggerTranslationBaseKey}.time_pattern.description.invalid`, + { + parts: formatListWithAnds( + hass.locale, + invalidParts.map((invalidPart) => + hass.localize( + `${triggerTranslationBaseKey}.time_pattern.${invalidPart}` + ) + ) + ), + } + ); + } + + return hass.localize( + `${triggerTranslationBaseKey}.time_pattern.description.full`, + { + secondsChoice: secondsChoice, + minutesChoice: minutesChoice, + hoursChoice: hoursChoice, + seconds: seconds, + minutes: minutes, + hours: hours, + secondsWithOrdinal: hass.localize( + `${triggerTranslationBaseKey}.time_pattern.description.ordinal`, + { + part: seconds, + } + ), + minutesWithOrdinal: hass.localize( + `${triggerTranslationBaseKey}.time_pattern.description.ordinal`, + { + part: minutes, + } + ), + hoursWithOrdinal: hass.localize( + `${triggerTranslationBaseKey}.time_pattern.description.ordinal`, + { + part: hours, + } + ), + } + ); } // Zone Trigger diff --git a/src/translations/en.json b/src/translations/en.json index 01cd81a568e1..bd741720b336 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2669,7 +2669,11 @@ "minutes": "Minutes", "seconds": "Seconds", "description": { - "picker": "Periodically, at a defined interval." + "picker": "Periodically, at a defined interval.", + "initial": "When a time pattern matches", + "invalid": "Invalid Time Pattern for {parts}", + "full": "Trigger {secondsChoice, select, \n every {every second of }\n every_interval {every {seconds} seconds of }\n on_the_xth {on the {secondsWithOrdinal} second of }\n other {}\n} {minutesChoice, select, \n every {every minute of }\n every_interval {every {minutes} minutes of }\n has_seconds {the {minutesWithOrdinal} minute of }\n on_the_xth {on the {minutesWithOrdinal} minute of }\n other {}\n} {hoursChoice, select, \n every {every hour}\n every_interval {every {hours} hours}\n has_seconds_or_minutes {the {hoursWithOrdinal} hour}\n on_the_xth {on the {hoursWithOrdinal} hour}\n other {}\n}", + "ordinal": "{part, selectordinal, \none {#st}\ntwo {#nd}\nfew {#rd}\nother {#th}\n}" } }, "webhook": { From 2451cf77f9476bd8dc7a46c0fd3e4a439d1d700e Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Mon, 8 Jan 2024 09:43:53 -0500 Subject: [PATCH 101/361] Fix various missing component imports (#19296) --- src/onboarding/onboarding-core-config.ts | 1 + src/panels/calendar/dialog-calendar-event-detail.ts | 1 + src/panels/calendar/dialog-calendar-event-editor.ts | 4 ++++ src/panels/config/core/ha-config-section-general.ts | 2 +- src/panels/todo/dialog-todo-item-editor.ts | 3 +++ 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/onboarding/onboarding-core-config.ts b/src/onboarding/onboarding-core-config.ts index 7849ecfee63d..61cdad8d01e0 100644 --- a/src/onboarding/onboarding-core-config.ts +++ b/src/onboarding/onboarding-core-config.ts @@ -12,6 +12,7 @@ import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../common/dom/fire_event"; import type { LocalizeFunc } from "../common/translations/localize"; import "../components/ha-alert"; +import "../components/ha-circular-progress"; import "../components/ha-country-picker"; import { ConfigUpdateValues, saveCoreConfig } from "../data/core"; import { countryCurrency } from "../data/currency"; diff --git a/src/panels/calendar/dialog-calendar-event-detail.ts b/src/panels/calendar/dialog-calendar-event-detail.ts index ee091eac1652..5962aa83f147 100644 --- a/src/panels/calendar/dialog-calendar-event-detail.ts +++ b/src/panels/calendar/dialog-calendar-event-detail.ts @@ -10,6 +10,7 @@ import { formatTime } from "../../common/datetime/format_time"; import { fireEvent } from "../../common/dom/fire_event"; import { isDate } from "../../common/string/is_date"; import "../../components/entity/state-info"; +import "../../components/ha-alert"; import "../../components/ha-date-input"; import { createCloseHeading } from "../../components/ha-dialog"; import "../../components/ha-time-input"; diff --git a/src/panels/calendar/dialog-calendar-event-editor.ts b/src/panels/calendar/dialog-calendar-event-editor.ts index e5925b1243e2..1f5e48ce9ddb 100644 --- a/src/panels/calendar/dialog-calendar-event-editor.ts +++ b/src/panels/calendar/dialog-calendar-event-editor.ts @@ -16,9 +16,13 @@ import { computeStateDomain } from "../../common/entity/compute_state_domain"; import { supportsFeature } from "../../common/entity/supports-feature"; import { isDate } from "../../common/string/is_date"; import "../../components/entity/ha-entity-picker"; +import "../../components/ha-alert"; import "../../components/ha-date-input"; import { createCloseHeading } from "../../components/ha-dialog"; +import "../../components/ha-formfield"; +import "../../components/ha-switch"; import "../../components/ha-textarea"; +import "../../components/ha-textfield"; import "../../components/ha-time-input"; import { CalendarEntityFeature, diff --git a/src/panels/config/core/ha-config-section-general.ts b/src/panels/config/core/ha-config-section-general.ts index 1d9e3794c0ac..22df34f25cfb 100644 --- a/src/panels/config/core/ha-config-section-general.ts +++ b/src/panels/config/core/ha-config-section-general.ts @@ -20,6 +20,7 @@ import type { HaRadio } from "../../../components/ha-radio"; import "../../../components/ha-select"; import "../../../components/ha-settings-row"; import "../../../components/ha-textfield"; +import type { HaTextField } from "../../../components/ha-textfield"; import "../../../components/ha-timezone-picker"; import "../../../components/map/ha-locations-editor"; import type { MarkerLocation } from "../../../components/map/ha-locations-editor"; @@ -28,7 +29,6 @@ import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box import "../../../layouts/hass-subpage"; import { haStyle } from "../../../resources/styles"; import type { HomeAssistant, ValueChangedEvent } from "../../../types"; -import type { HaTextField } from "../../../components/ha-textfield"; @customElement("ha-config-section-general") class HaConfigSectionGeneral extends LitElement { diff --git a/src/panels/todo/dialog-todo-item-editor.ts b/src/panels/todo/dialog-todo-item-editor.ts index be03e260eccf..44a52d907ce4 100644 --- a/src/panels/todo/dialog-todo-item-editor.ts +++ b/src/panels/todo/dialog-todo-item-editor.ts @@ -5,9 +5,12 @@ import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../common/dom/fire_event"; import { supportsFeature } from "../../common/entity/supports-feature"; +import "../../components/ha-alert"; +import "../../components/ha-checkbox"; import "../../components/ha-date-input"; import { createCloseHeading } from "../../components/ha-dialog"; import "../../components/ha-textarea"; +import "../../components/ha-textfield"; import "../../components/ha-time-input"; import { TodoItemStatus, From d4ec608123f852753b578e8ae5d7c1940b1e564c Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Mon, 8 Jan 2024 09:45:24 -0500 Subject: [PATCH 102/361] Fix invalid media queries in calendar and todo editors (#19295) --- src/panels/calendar/dialog-calendar-event-editor.ts | 2 +- src/panels/todo/dialog-todo-item-editor.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/panels/calendar/dialog-calendar-event-editor.ts b/src/panels/calendar/dialog-calendar-event-editor.ts index 1f5e48ce9ddb..e1db40da695d 100644 --- a/src/panels/calendar/dialog-calendar-event-editor.ts +++ b/src/panels/calendar/dialog-calendar-event-editor.ts @@ -581,7 +581,7 @@ class DialogCalendarEventEditor extends LitElement { return [ haStyleDialog, css` - @media all and (min-width: 450px and min-height: 500px) { + @media all and (min-width: 450px) and (min-height: 500px) { ha-dialog { --mdc-dialog-min-width: min(600px, 95vw); --mdc-dialog-max-width: min(600px, 95vw); diff --git a/src/panels/todo/dialog-todo-item-editor.ts b/src/panels/todo/dialog-todo-item-editor.ts index 44a52d907ce4..1afb0f66e4fe 100644 --- a/src/panels/todo/dialog-todo-item-editor.ts +++ b/src/panels/todo/dialog-todo-item-editor.ts @@ -385,7 +385,7 @@ class DialogTodoItemEditor extends LitElement { return [ haStyleDialog, css` - @media all and (min-width: 450px and min-height: 500px) { + @media all and (min-width: 450px) and (min-height: 500px) { ha-dialog { --mdc-dialog-min-width: min(600px, 95vw); --mdc-dialog-max-width: min(600px, 95vw); From 056eb888f3681a797e72819544a3f4b6233364f3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 20:56:32 -0500 Subject: [PATCH 103/361] Update dependency @types/chromecast-caf-receiver to v6.0.13 (#19332) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index b591fab97d7c..d98a7fd9c623 100644 --- a/package.json +++ b/package.json @@ -168,7 +168,7 @@ "@rollup/plugin-node-resolve": "15.2.3", "@rollup/plugin-replace": "5.0.5", "@types/babel__plugin-transform-runtime": "7.9.5", - "@types/chromecast-caf-receiver": "6.0.12", + "@types/chromecast-caf-receiver": "6.0.13", "@types/chromecast-caf-sender": "1.0.8", "@types/glob": "8.1.0", "@types/html-minifier-terser": "7.0.2", diff --git a/yarn.lock b/yarn.lock index 70e9ccb6e016..6b5dca8d072a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3988,10 +3988,10 @@ __metadata: languageName: node linkType: hard -"@types/chromecast-caf-receiver@npm:6.0.12": - version: 6.0.12 - resolution: "@types/chromecast-caf-receiver@npm:6.0.12" - checksum: f4bef9d3106b19aa8a85a3d41d4eb7b4d86c334275d829bce7194f6c4afc0b23a5b056899d97c5bc639211a00bf4506259e85b9935545b8502218cde77296442 +"@types/chromecast-caf-receiver@npm:6.0.13": + version: 6.0.13 + resolution: "@types/chromecast-caf-receiver@npm:6.0.13" + checksum: 4e2fb8628985cd61f206de5dfe6f3bcbcb2527024f03e36c6cad844fe7672ecd1c2b14cd2b91987f3ab0f67a8b6430008e2a567cfa6b5df8cb09b204e7b72094 languageName: node linkType: hard @@ -9556,7 +9556,7 @@ __metadata: "@rollup/plugin-replace": "npm:5.0.5" "@thomasloven/round-slider": "npm:0.6.0" "@types/babel__plugin-transform-runtime": "npm:7.9.5" - "@types/chromecast-caf-receiver": "npm:6.0.12" + "@types/chromecast-caf-receiver": "npm:6.0.13" "@types/chromecast-caf-sender": "npm:1.0.8" "@types/glob": "npm:8.1.0" "@types/html-minifier-terser": "npm:7.0.2" From 80b1a6297be33783d900ef24026c0e88fe3ff1bb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 20:57:22 -0500 Subject: [PATCH 104/361] Update dependency @types/luxon to v3.4.0 (#19333) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index d98a7fd9c623..dc36dcc68d9b 100644 --- a/package.json +++ b/package.json @@ -175,7 +175,7 @@ "@types/js-yaml": "4.0.9", "@types/leaflet": "1.9.8", "@types/leaflet-draw": "1.0.11", - "@types/luxon": "3.3.8", + "@types/luxon": "3.4.0", "@types/mocha": "10.0.6", "@types/qrcode": "1.5.5", "@types/serve-handler": "6.1.4", diff --git a/yarn.lock b/yarn.lock index 6b5dca8d072a..e138ec3bce88 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4271,10 +4271,10 @@ __metadata: languageName: node linkType: hard -"@types/luxon@npm:3.3.8": - version: 3.3.8 - resolution: "@types/luxon@npm:3.3.8" - checksum: 2176c394e7ee3b8580e9f30bedac29048fabe32589c6561a9654b242b9c2c08ff9b93206f0eca07e495f900a352ac1446236c310eacda574b3c2d6238a9173a7 +"@types/luxon@npm:3.4.0": + version: 3.4.0 + resolution: "@types/luxon@npm:3.4.0" + checksum: cafe745e81765e71230a42520caf77d69556e22d50a464dcebd3b7da3989ab9c137de54dbfef60639ea4274326a57b762120c0088d3fb093c25f1ca752146c64 languageName: node linkType: hard @@ -9563,7 +9563,7 @@ __metadata: "@types/js-yaml": "npm:4.0.9" "@types/leaflet": "npm:1.9.8" "@types/leaflet-draw": "npm:1.0.11" - "@types/luxon": "npm:3.3.8" + "@types/luxon": "npm:3.4.0" "@types/mocha": "npm:10.0.6" "@types/qrcode": "npm:1.5.5" "@types/serve-handler": "npm:6.1.4" From 03a1c21f3428d675a6e825c47b31d525cdd65eb9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 21:14:38 -0500 Subject: [PATCH 105/361] Bump follow-redirects from 1.15.3 to 1.15.4 (#19336) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e138ec3bce88..b008f90c71f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8679,12 +8679,12 @@ __metadata: linkType: hard "follow-redirects@npm:^1.0.0": - version: 1.15.3 - resolution: "follow-redirects@npm:1.15.3" + version: 1.15.4 + resolution: "follow-redirects@npm:1.15.4" peerDependenciesMeta: debug: optional: true - checksum: 60d98693f4976892f8c654b16ef6d1803887a951898857ab0cdc009570b1c06314ad499505b7a040ac5b98144939f8597766e5e6a6859c0945d157b473aa6f5f + checksum: 2e8f5f259a6b02dfa8dc199e08431848a7c3beed32eb4c19945966164a52c89f07b86c3afcc32ebe4279cf0a960520e45a63013d6350309c5ec90133c5d9351a languageName: node linkType: hard From 3edc77c978981bb50ec4141cee99d7ba0d5e0d96 Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Tue, 9 Jan 2024 09:00:30 -0500 Subject: [PATCH 106/361] Fix missing element tag definitions (#19329) --- gallery/src/pages/automation/editor-condition.ts | 4 ++-- gallery/src/pages/automation/editor-trigger.ts | 4 ++-- gallery/src/pages/lovelace/media-player-row.ts | 4 ++-- gallery/src/pages/misc/util-long-press.ts | 6 ++++++ hassio/src/addon-store/hassio-addon-repository.ts | 6 ++++++ hassio/src/addon-store/hassio-addon-store.ts | 6 ++++++ hassio/src/dashboard/hassio-update.ts | 6 ++++++ src/auth/ha-authorize.ts | 6 ++++++ src/auth/ha-pick-auth-provider.ts | 3 +++ src/components/entity/ha-entity-toggle.ts | 15 ++++++++++----- src/components/ha-gauge.ts | 8 +++++++- src/components/ha-qr-code.ts | 6 ++++++ .../ha-selector/ha-selector-backup-location.ts | 2 +- .../ha-selector/ha-selector-tts-voice.ts | 2 +- .../ha-selector/ha-selector-ui-action.ts | 2 +- .../ha-selector/ha-selector-ui-color.ts | 2 +- src/components/ha-two-pane-top-app-bar-fixed.ts | 8 +++++++- .../zha/ha-device-info-zha.ts | 8 +++++++- .../settings/entity-settings-helper-tab.ts | 4 ++-- src/panels/config/helpers/ha-config-helpers.ts | 6 ++++++ .../matter/matter-config-dashboard.ts | 6 ++++++ .../integration-panels/mqtt/mqtt-config-panel.ts | 4 ++-- .../integration-panels/zha/zha-add-group-page.ts | 6 ++++++ .../integration-panels/zha/zha-group-page.ts | 6 ++++++ .../zha/zha-network-visualization-page.ts | 6 ++++++ .../dashboards/ha-config-lovelace-dashboards.ts | 6 ++++++ .../resources/ha-config-lovelace-resources.ts | 6 ++++++ src/panels/config/person/ha-config-person.ts | 11 ++++++++--- .../ha-config-voice-assistants-assistants.ts | 6 ++++++ src/panels/config/zone/ha-config-zone.ts | 6 ++++++ .../energy/strategies/energy-view-strategy.ts | 6 ++++++ src/panels/logbook/ha-panel-logbook.ts | 6 ++++++ .../lovelace/badges/hui-entity-filter-badge.ts | 15 ++++++++++++--- .../lovelace/cards/hui-entity-filter-card.ts | 15 ++++++++++++--- .../lovelace/cards/hui-horizontal-stack-card.ts | 8 ++++---- .../lovelace/components/hui-generic-entity-row.ts | 12 +++++++++--- src/panels/lovelace/ha-panel-lovelace.ts | 6 ++++++ .../original-states-dashboard-strategy.ts | 6 ++++++ .../strategies/original-states-view-strategy.ts | 6 ++++++ src/state-summary/state-card-update.ts | 6 ++++++ tsconfig.json | 2 +- 41 files changed, 220 insertions(+), 39 deletions(-) diff --git a/gallery/src/pages/automation/editor-condition.ts b/gallery/src/pages/automation/editor-condition.ts index 3a43eda71e0f..ed30c74272d7 100644 --- a/gallery/src/pages/automation/editor-condition.ts +++ b/gallery/src/pages/automation/editor-condition.ts @@ -80,7 +80,7 @@ const SCHEMAS: { name: string; conditions: ConditionWithShorthand[] }[] = [ ]; @customElement("demo-automation-editor-condition") -class DemoHaAutomationEditorCondition extends LitElement { +export class DemoAutomationEditorCondition extends LitElement { @state() private hass!: HomeAssistant; @state() private _disabled = false; @@ -155,6 +155,6 @@ class DemoHaAutomationEditorCondition extends LitElement { declare global { interface HTMLElementTagNameMap { - "demo-ha-automation-editor-condition": DemoHaAutomationEditorCondition; + "demo-automation-editor-condition": DemoAutomationEditorCondition; } } diff --git a/gallery/src/pages/automation/editor-trigger.ts b/gallery/src/pages/automation/editor-trigger.ts index 30c9721256e8..1ed11eb0a87c 100644 --- a/gallery/src/pages/automation/editor-trigger.ts +++ b/gallery/src/pages/automation/editor-trigger.ts @@ -126,7 +126,7 @@ const SCHEMAS: { name: string; triggers: Trigger[] }[] = [ ]; @customElement("demo-automation-editor-trigger") -class DemoHaAutomationEditorTrigger extends LitElement { +export class DemoAutomationEditorTrigger extends LitElement { @state() private hass!: HomeAssistant; @state() private _disabled = false; @@ -201,6 +201,6 @@ class DemoHaAutomationEditorTrigger extends LitElement { declare global { interface HTMLElementTagNameMap { - "demo-ha-automation-editor-trigger": DemoHaAutomationEditorTrigger; + "demo-automation-editor-trigger": DemoAutomationEditorTrigger; } } diff --git a/gallery/src/pages/lovelace/media-player-row.ts b/gallery/src/pages/lovelace/media-player-row.ts index 44433bc089be..eeba128c0630 100644 --- a/gallery/src/pages/lovelace/media-player-row.ts +++ b/gallery/src/pages/lovelace/media-player-row.ts @@ -55,7 +55,7 @@ const CONFIGS = [ ]; @customElement("demo-lovelace-media-player-row") -class DemoHuiMediaPlayerRow extends LitElement { +export class DemoLovelaceMediaPlayerRow extends LitElement { @query("#demos") private _demoRoot!: HTMLElement; protected render(): TemplateResult { @@ -73,6 +73,6 @@ class DemoHuiMediaPlayerRow extends LitElement { declare global { interface HTMLElementTagNameMap { - "demo-lovelace-media-player-rows": DemoHuiMediaPlayerRow; + "demo-lovelace-media-player-row": DemoLovelaceMediaPlayerRow; } } diff --git a/gallery/src/pages/misc/util-long-press.ts b/gallery/src/pages/misc/util-long-press.ts index 7ce2106ba236..05b4f6291e33 100644 --- a/gallery/src/pages/misc/util-long-press.ts +++ b/gallery/src/pages/misc/util-long-press.ts @@ -59,3 +59,9 @@ export class DemoUtilLongPress extends LitElement { } `; } + +declare global { + interface HTMLElementTagNameMap { + "demo-misc-util-long-press": DemoUtilLongPress; + } +} diff --git a/hassio/src/addon-store/hassio-addon-repository.ts b/hassio/src/addon-store/hassio-addon-repository.ts index 477a4361ab14..3c7ee0156608 100644 --- a/hassio/src/addon-store/hassio-addon-repository.ts +++ b/hassio/src/addon-store/hassio-addon-repository.ts @@ -140,3 +140,9 @@ export class HassioAddonRepositoryEl extends LitElement { ]; } } + +declare global { + interface HTMLElementTagNameMap { + "hassio-addon-repository": HassioAddonRepositoryEl; + } +} diff --git a/hassio/src/addon-store/hassio-addon-store.ts b/hassio/src/addon-store/hassio-addon-store.ts index a918c348203d..695f41df6db2 100644 --- a/hassio/src/addon-store/hassio-addon-store.ts +++ b/hassio/src/addon-store/hassio-addon-store.ts @@ -248,3 +248,9 @@ export class HassioAddonStore extends LitElement { `; } } + +declare global { + interface HTMLElementTagNameMap { + "hassio-addon-store": HassioAddonStore; + } +} diff --git a/hassio/src/dashboard/hassio-update.ts b/hassio/src/dashboard/hassio-update.ts index b331dc7609b6..b79aa14f18aa 100644 --- a/hassio/src/dashboard/hassio-update.ts +++ b/hassio/src/dashboard/hassio-update.ts @@ -151,3 +151,9 @@ export class HassioUpdate extends LitElement { ]; } } + +declare global { + interface HTMLElementTagNameMap { + "hassio-update": HassioUpdate; + } +} diff --git a/src/auth/ha-authorize.ts b/src/auth/ha-authorize.ts index 6af166f067ce..97fc3ef4790d 100644 --- a/src/auth/ha-authorize.ts +++ b/src/auth/ha-authorize.ts @@ -352,3 +352,9 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) { } } } + +declare global { + interface HTMLElementTagNameMap { + "ha-authorize": HaAuthorize; + } +} diff --git a/src/auth/ha-pick-auth-provider.ts b/src/auth/ha-pick-auth-provider.ts index 90a5c238b67b..e26030146cf9 100644 --- a/src/auth/ha-pick-auth-provider.ts +++ b/src/auth/ha-pick-auth-provider.ts @@ -8,6 +8,9 @@ import "../components/ha-list-item"; import { AuthProvider } from "../data/auth"; declare global { + interface HTMLElementTagNameMap { + "ha-pick-auth-provider": HaPickAuthProvider; + } interface HASSDomEvents { "pick-auth-provider": AuthProvider; } diff --git a/src/components/entity/ha-entity-toggle.ts b/src/components/entity/ha-entity-toggle.ts index 223b208e1e97..ba1da0e6a9c4 100644 --- a/src/components/entity/ha-entity-toggle.ts +++ b/src/components/entity/ha-entity-toggle.ts @@ -1,18 +1,18 @@ import { mdiFlash, mdiFlashOff } from "@mdi/js"; import { HassEntity } from "home-assistant-js-websocket"; import { - css, CSSResultGroup, - html, LitElement, PropertyValues, TemplateResult, + css, + html, } from "lit"; -import { property, state } from "lit/decorators"; +import { customElement, property, state } from "lit/decorators"; import { STATES_OFF } from "../../common/const"; import { computeStateDomain } from "../../common/entity/compute_state_domain"; import { computeStateName } from "../../common/entity/compute_state_name"; -import { isUnavailableState, UNAVAILABLE, UNKNOWN } from "../../data/entity"; +import { UNAVAILABLE, UNKNOWN, isUnavailableState } from "../../data/entity"; import { forwardHaptic } from "../../data/haptics"; import { HomeAssistant } from "../../types"; import "../ha-formfield"; @@ -24,6 +24,7 @@ const isOn = (stateObj?: HassEntity) => !STATES_OFF.includes(stateObj.state) && !isUnavailableState(stateObj.state); +@customElement("ha-entity-toggle") export class HaEntityToggle extends LitElement { // hass is not a property so that we only re-render on stateObj changes public hass?: HomeAssistant; @@ -175,4 +176,8 @@ export class HaEntityToggle extends LitElement { } } -customElements.define("ha-entity-toggle", HaEntityToggle); +declare global { + interface HTMLElementTagNameMap { + "ha-entity-toggle": HaEntityToggle; + } +} diff --git a/src/components/ha-gauge.ts b/src/components/ha-gauge.ts index 53b573dc47db..de8322e1d85c 100644 --- a/src/components/ha-gauge.ts +++ b/src/components/ha-gauge.ts @@ -19,7 +19,7 @@ export interface LevelDefinition { } @customElement("ha-gauge") -export class Gauge extends LitElement { +export class HaGauge extends LitElement { @property({ type: Number }) public min = 0; @property({ type: Number }) public max = 100; @@ -216,3 +216,9 @@ export class Gauge extends LitElement { `; } } + +declare global { + interface HTMLElementTagNameMap { + "ha-gauge": HaGauge; + } +} diff --git a/src/components/ha-qr-code.ts b/src/components/ha-qr-code.ts index f6a686d06823..2c0228e9a430 100644 --- a/src/components/ha-qr-code.ts +++ b/src/components/ha-qr-code.ts @@ -112,3 +112,9 @@ export class HaQrCode extends LitElement { } `; } + +declare global { + interface HTMLElementTagNameMap { + "ha-qr-code": HaQrCode; + } +} diff --git a/src/components/ha-selector/ha-selector-backup-location.ts b/src/components/ha-selector/ha-selector-backup-location.ts index f20c447a7bfc..0a98806b8362 100644 --- a/src/components/ha-selector/ha-selector-backup-location.ts +++ b/src/components/ha-selector/ha-selector-backup-location.ts @@ -41,6 +41,6 @@ export class HaBackupLocationSelector extends LitElement { declare global { interface HTMLElementTagNameMap { - "ha-selector-backup-location": HaBackupLocationSelector; + "ha-selector-backup_location": HaBackupLocationSelector; } } diff --git a/src/components/ha-selector/ha-selector-tts-voice.ts b/src/components/ha-selector/ha-selector-tts-voice.ts index dc6b0c0fdc66..6098ed7ebb34 100644 --- a/src/components/ha-selector/ha-selector-tts-voice.ts +++ b/src/components/ha-selector/ha-selector-tts-voice.ts @@ -47,6 +47,6 @@ export class HaTTSVoiceSelector extends LitElement { declare global { interface HTMLElementTagNameMap { - "ha-selector-tts-voice": HaTTSVoiceSelector; + "ha-selector-tts_voice": HaTTSVoiceSelector; } } diff --git a/src/components/ha-selector/ha-selector-ui-action.ts b/src/components/ha-selector/ha-selector-ui-action.ts index 7888ec1128fa..34c71d280dfa 100644 --- a/src/components/ha-selector/ha-selector-ui-action.ts +++ b/src/components/ha-selector/ha-selector-ui-action.ts @@ -39,6 +39,6 @@ export class HaSelectorUiAction extends LitElement { declare global { interface HTMLElementTagNameMap { - "ha-selector-ui-action": HaSelectorUiAction; + "ha-selector-ui_action": HaSelectorUiAction; } } diff --git a/src/components/ha-selector/ha-selector-ui-color.ts b/src/components/ha-selector/ha-selector-ui-color.ts index 4d77d1e213f2..c88c083f8ef0 100644 --- a/src/components/ha-selector/ha-selector-ui-color.ts +++ b/src/components/ha-selector/ha-selector-ui-color.ts @@ -36,6 +36,6 @@ export class HaSelectorUiColor extends LitElement { declare global { interface HTMLElementTagNameMap { - "ha-selector-ui-color": HaSelectorUiColor; + "ha-selector-ui_color": HaSelectorUiColor; } } diff --git a/src/components/ha-two-pane-top-app-bar-fixed.ts b/src/components/ha-two-pane-top-app-bar-fixed.ts index df6477534c54..5cd5dbb2a234 100644 --- a/src/components/ha-two-pane-top-app-bar-fixed.ts +++ b/src/components/ha-two-pane-top-app-bar-fixed.ts @@ -17,7 +17,7 @@ export const passiveEventOptionsIfSupported = supportsPassiveEventListener : undefined; @customElement("ha-two-pane-top-app-bar-fixed") -export abstract class TopAppBarBaseBase extends BaseElement { +export class TopAppBarBaseBase extends BaseElement { protected override mdcFoundation!: MDCFixedTopAppBarFoundation; protected override mdcFoundationClass = MDCFixedTopAppBarFoundation; @@ -323,3 +323,9 @@ export abstract class TopAppBarBaseBase extends BaseElement { `, ]; } + +declare global { + interface HTMLElementTagNameMap { + "ha-two-pane-top-app-bar-fixed": TopAppBarBaseBase; + } +} diff --git a/src/panels/config/devices/device-detail/integration-elements/zha/ha-device-info-zha.ts b/src/panels/config/devices/device-detail/integration-elements/zha/ha-device-info-zha.ts index 227cfbd04313..da52b4dd2467 100644 --- a/src/panels/config/devices/device-detail/integration-elements/zha/ha-device-info-zha.ts +++ b/src/panels/config/devices/device-detail/integration-elements/zha/ha-device-info-zha.ts @@ -15,7 +15,7 @@ import { HomeAssistant } from "../../../../../../types"; import { formatAsPaddedHex } from "../../../../integrations/integration-panels/zha/functions"; @customElement("ha-device-info-zha") -export class HaDeviceActionsZha extends LitElement { +export class HaDeviceInfoZha extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @property() public device!: DeviceRegistryEntry; @@ -98,3 +98,9 @@ export class HaDeviceActionsZha extends LitElement { ]; } } + +declare global { + interface HTMLElementTagNameMap { + "ha-device-info-zha": HaDeviceInfoZha; + } +} diff --git a/src/panels/config/entities/editor-tabs/settings/entity-settings-helper-tab.ts b/src/panels/config/entities/editor-tabs/settings/entity-settings-helper-tab.ts index 4aa558799462..dbe61afa3d6a 100644 --- a/src/panels/config/entities/editor-tabs/settings/entity-settings-helper-tab.ts +++ b/src/panels/config/entities/editor-tabs/settings/entity-settings-helper-tab.ts @@ -33,7 +33,7 @@ import "../../entity-registry-settings-editor"; import type { EntityRegistrySettingsEditor } from "../../entity-registry-settings-editor"; @customElement("entity-settings-helper-tab") -export class EntityRegistrySettingsHelper extends LitElement { +export class EntitySettingsHelperTab extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @property() public entry!: ExtEntityRegistryEntry; @@ -226,6 +226,6 @@ export class EntityRegistrySettingsHelper extends LitElement { declare global { interface HTMLElementTagNameMap { - "entity-platform-helper-tab": EntityRegistrySettingsHelper; + "entity-settings-helper-tab": EntitySettingsHelperTab; } } diff --git a/src/panels/config/helpers/ha-config-helpers.ts b/src/panels/config/helpers/ha-config-helpers.ts index ac517776f3f7..1982716efc61 100644 --- a/src/panels/config/helpers/ha-config-helpers.ts +++ b/src/panels/config/helpers/ha-config-helpers.ts @@ -418,3 +418,9 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) { showHelperDetailDialog(this, {}); } } + +declare global { + interface HTMLElementTagNameMap { + "ha-config-helpers": HaConfigHelpers; + } +} diff --git a/src/panels/config/integrations/integration-panels/matter/matter-config-dashboard.ts b/src/panels/config/integrations/integration-panels/matter/matter-config-dashboard.ts index 29e4a6265099..9eaa14ec3435 100644 --- a/src/panels/config/integrations/integration-panels/matter/matter-config-dashboard.ts +++ b/src/panels/config/integrations/integration-panels/matter/matter-config-dashboard.ts @@ -210,3 +210,9 @@ export class MatterConfigDashboard extends LitElement { `, ]; } + +declare global { + interface HTMLElementTagNameMap { + "matter-config-dashboard": MatterConfigDashboard; + } +} diff --git a/src/panels/config/integrations/integration-panels/mqtt/mqtt-config-panel.ts b/src/panels/config/integrations/integration-panels/mqtt/mqtt-config-panel.ts index 032ebf38edc1..76ebc93326e1 100644 --- a/src/panels/config/integrations/integration-panels/mqtt/mqtt-config-panel.ts +++ b/src/panels/config/integrations/integration-panels/mqtt/mqtt-config-panel.ts @@ -16,7 +16,7 @@ import "./mqtt-subscribe-card"; const qosLevel = ["0", "1", "2"]; @customElement("mqtt-config-panel") -class HaPanelDevMqtt extends LitElement { +export class MQTTConfigPanel extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @property({ type: Boolean }) public narrow!: boolean; @@ -248,6 +248,6 @@ class HaPanelDevMqtt extends LitElement { declare global { interface HTMLElementTagNameMap { - "developer-tools-mqtt": HaPanelDevMqtt; + "mqtt-config-panel": MQTTConfigPanel; } } diff --git a/src/panels/config/integrations/integration-panels/zha/zha-add-group-page.ts b/src/panels/config/integrations/integration-panels/zha/zha-add-group-page.ts index 367485563c1b..2b13eb3d0868 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-add-group-page.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-add-group-page.ts @@ -198,3 +198,9 @@ export class ZHAAddGroupPage extends LitElement { ]; } } + +declare global { + interface HTMLElementTagNameMap { + "zha-add-group-page": ZHAAddGroupPage; + } +} diff --git a/src/panels/config/integrations/integration-panels/zha/zha-group-page.ts b/src/panels/config/integrations/integration-panels/zha/zha-group-page.ts index 7fde6ee13b47..f76583920656 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-group-page.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-group-page.ts @@ -324,3 +324,9 @@ export class ZHAGroupPage extends LitElement { ]; } } + +declare global { + interface HTMLElementTagNameMap { + "zha-group-page": ZHAGroupPage; + } +} diff --git a/src/panels/config/integrations/integration-panels/zha/zha-network-visualization-page.ts b/src/panels/config/integrations/integration-panels/zha/zha-network-visualization-page.ts index 706c0e9b736d..2d9cd4bd9410 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-network-visualization-page.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-network-visualization-page.ts @@ -472,3 +472,9 @@ export class ZHANetworkVisualizationPage extends LitElement { ]; } } + +declare global { + interface HTMLElementTagNameMap { + "zha-network-visualization-page": ZHANetworkVisualizationPage; + } +} diff --git a/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts b/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts index f246a48a1ba5..de05a5a0d6af 100644 --- a/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts +++ b/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts @@ -407,3 +407,9 @@ export class HaConfigLovelaceDashboards extends LitElement { }); } } + +declare global { + interface HTMLElementTagNameMap { + "ha-config-lovelace-dashboards": HaConfigLovelaceDashboards; + } +} diff --git a/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts b/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts index ec4b8f77d58d..71df3c3354da 100644 --- a/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts +++ b/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts @@ -253,3 +253,9 @@ export class HaConfigLovelaceRescources extends LitElement { ]; } } + +declare global { + interface HTMLElementTagNameMap { + "ha-config-lovelace-resources": HaConfigLovelaceRescources; + } +} diff --git a/src/panels/config/person/ha-config-person.ts b/src/panels/config/person/ha-config-person.ts index 61a54c258298..60311cd901eb 100644 --- a/src/panels/config/person/ha-config-person.ts +++ b/src/panels/config/person/ha-config-person.ts @@ -2,7 +2,7 @@ import { mdiPlus } from "@mdi/js"; import "@polymer/paper-item/paper-icon-item"; import "@polymer/paper-item/paper-item-body"; import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; -import { property, state } from "lit/decorators"; +import { customElement, property, state } from "lit/decorators"; import { stringCompare } from "../../../common/string/compare"; import "../../../components/ha-card"; import "../../../components/ha-fab"; @@ -31,7 +31,8 @@ import { showPersonDetailDialog, } from "./show-dialog-person-detail"; -class HaConfigPerson extends LitElement { +@customElement("ha-config-person") +export class HaConfigPerson extends LitElement { @property({ attribute: false }) public hass?: HomeAssistant; @property() public isWide?: boolean; @@ -292,4 +293,8 @@ class HaConfigPerson extends LitElement { } } -customElements.define("ha-config-person", HaConfigPerson); +declare global { + interface HTMLElementTagNameMap { + "ha-config-person": HaConfigPerson; + } +} diff --git a/src/panels/config/voice-assistants/ha-config-voice-assistants-assistants.ts b/src/panels/config/voice-assistants/ha-config-voice-assistants-assistants.ts index e88e0d9128e2..c932806fa89b 100644 --- a/src/panels/config/voice-assistants/ha-config-voice-assistants-assistants.ts +++ b/src/panels/config/voice-assistants/ha-config-voice-assistants-assistants.ts @@ -96,3 +96,9 @@ export class HaConfigVoiceAssistantsAssistants extends LitElement { } `; } + +declare global { + interface HTMLElementTagNameMap { + "ha-config-voice-assistants-assistants": HaConfigVoiceAssistantsAssistants; + } +} diff --git a/src/panels/config/zone/ha-config-zone.ts b/src/panels/config/zone/ha-config-zone.ts index c3e302cdd706..cbe1af87ddce 100644 --- a/src/panels/config/zone/ha-config-zone.ts +++ b/src/panels/config/zone/ha-config-zone.ts @@ -548,3 +548,9 @@ export class HaConfigZone extends SubscribeMixin(LitElement) { `; } } + +declare global { + interface HTMLElementTagNameMap { + "ha-config-zone": HaConfigZone; + } +} diff --git a/src/panels/energy/strategies/energy-view-strategy.ts b/src/panels/energy/strategies/energy-view-strategy.ts index 0ca612065de9..27a0a9137184 100644 --- a/src/panels/energy/strategies/energy-view-strategy.ts +++ b/src/panels/energy/strategies/energy-view-strategy.ts @@ -166,3 +166,9 @@ export class EnergyViewStrategy extends ReactiveElement { return view; } } + +declare global { + interface HTMLElementTagNameMap { + "energy-view-strategy": EnergyViewStrategy; + } +} diff --git a/src/panels/logbook/ha-panel-logbook.ts b/src/panels/logbook/ha-panel-logbook.ts index d192b53edb65..2d4b754f548e 100644 --- a/src/panels/logbook/ha-panel-logbook.ts +++ b/src/panels/logbook/ha-panel-logbook.ts @@ -274,3 +274,9 @@ export class HaPanelLogbook extends LitElement { ]; } } + +declare global { + interface HTMLElementTagNameMap { + "ha-panel-logbook": HaPanelLogbook; + } +} diff --git a/src/panels/lovelace/badges/hui-entity-filter-badge.ts b/src/panels/lovelace/badges/hui-entity-filter-badge.ts index a45799695ac8..04cdd94a0f05 100644 --- a/src/panels/lovelace/badges/hui-entity-filter-badge.ts +++ b/src/panels/lovelace/badges/hui-entity-filter-badge.ts @@ -1,5 +1,5 @@ import { PropertyValues, ReactiveElement } from "lit"; -import { property, state } from "lit/decorators"; +import { customElement, property, state } from "lit/decorators"; import { HomeAssistant } from "../../../types"; import { evaluateFilter } from "../common/evaluate-filter"; import { processConfigEntities } from "../common/process-config-entities"; @@ -8,7 +8,11 @@ import { EntityFilterEntityConfig } from "../entity-rows/types"; import { LovelaceBadge } from "../types"; import { EntityFilterBadgeConfig } from "./types"; -class EntityFilterBadge extends ReactiveElement implements LovelaceBadge { +@customElement("hui-entity-filter-badge") +export class HuiEntityFilterBadge + extends ReactiveElement + implements LovelaceBadge +{ @property({ attribute: false }) public hass!: HomeAssistant; @state() private _config?: EntityFilterBadgeConfig; @@ -153,4 +157,9 @@ class EntityFilterBadge extends ReactiveElement implements LovelaceBadge { return false; } } -customElements.define("hui-entity-filter-badge", EntityFilterBadge); + +declare global { + interface HTMLElementTagNameMap { + "hui-entity-filter-badge": HuiEntityFilterBadge; + } +} diff --git a/src/panels/lovelace/cards/hui-entity-filter-card.ts b/src/panels/lovelace/cards/hui-entity-filter-card.ts index ebd649bc530f..797d7114a74b 100644 --- a/src/panels/lovelace/cards/hui-entity-filter-card.ts +++ b/src/panels/lovelace/cards/hui-entity-filter-card.ts @@ -1,5 +1,5 @@ import { PropertyValues, ReactiveElement } from "lit"; -import { property, state } from "lit/decorators"; +import { customElement, property, state } from "lit/decorators"; import { LovelaceCardConfig } from "../../../data/lovelace/config/card"; import { HomeAssistant } from "../../../types"; import { computeCardSize } from "../common/compute-card-size"; @@ -11,7 +11,11 @@ import { EntityFilterEntityConfig } from "../entity-rows/types"; import { LovelaceCard } from "../types"; import { EntityFilterCardConfig } from "./types"; -class EntityFilterCard extends ReactiveElement implements LovelaceCard { +@customElement("hui-entity-filter-card") +export class HuiEntityFilterCard + extends ReactiveElement + implements LovelaceCard +{ public static getStubConfig( hass: HomeAssistant, entities: string[], @@ -230,4 +234,9 @@ class EntityFilterCard extends ReactiveElement implements LovelaceCard { this._element = newCardEl; } } -customElements.define("hui-entity-filter-card", EntityFilterCard); + +declare global { + interface HTMLElementTagNameMap { + "hui-entity-filter-card": HuiEntityFilterCard; + } +} diff --git a/src/panels/lovelace/cards/hui-horizontal-stack-card.ts b/src/panels/lovelace/cards/hui-horizontal-stack-card.ts index 349f5867b701..72da14e3ea67 100644 --- a/src/panels/lovelace/cards/hui-horizontal-stack-card.ts +++ b/src/panels/lovelace/cards/hui-horizontal-stack-card.ts @@ -1,8 +1,10 @@ import { css, CSSResultGroup } from "lit"; +import { customElement } from "lit/decorators"; import { computeCardSize } from "../common/compute-card-size"; import { HuiStackCard } from "./hui-stack-card"; -class HuiHorizontalStackCard extends HuiStackCard { +@customElement("hui-horizontal-stack-card") +export class HuiHorizontalStackCard extends HuiStackCard { public async getCardSize(): Promise { if (!this._cards) { return 0; @@ -48,8 +50,6 @@ class HuiHorizontalStackCard extends HuiStackCard { declare global { interface HTMLElementTagNameMap { - "hui-horitzontal-stack-card": HuiHorizontalStackCard; + "hui-horizontal-stack-card": HuiHorizontalStackCard; } } - -customElements.define("hui-horizontal-stack-card", HuiHorizontalStackCard); diff --git a/src/panels/lovelace/components/hui-generic-entity-row.ts b/src/panels/lovelace/components/hui-generic-entity-row.ts index 4a6c8d920958..d426fde1fd35 100644 --- a/src/panels/lovelace/components/hui-generic-entity-row.ts +++ b/src/panels/lovelace/components/hui-generic-entity-row.ts @@ -6,7 +6,7 @@ import { html, nothing, } from "lit"; -import { property } from "lit/decorators"; +import { customElement, property } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { ifDefined } from "lit/directives/if-defined"; import { DOMAINS_INPUT_ROW } from "../../../common/const"; @@ -24,7 +24,8 @@ import { handleAction } from "../common/handle-action"; import { hasAction } from "../common/has-action"; import { createEntityNotFoundWarning } from "./hui-warning"; -class HuiGenericEntityRow extends LitElement { +@customElement("hui-generic-entity-row") +export class HuiGenericEntityRow extends LitElement { @property({ attribute: false }) public hass?: HomeAssistant; @property() public config?: EntitiesCardEntityConfig; @@ -249,4 +250,9 @@ class HuiGenericEntityRow extends LitElement { `; } } -customElements.define("hui-generic-entity-row", HuiGenericEntityRow); + +declare global { + interface HTMLElementTagNameMap { + "hui-generic-entity-row": HuiGenericEntityRow; + } +} diff --git a/src/panels/lovelace/ha-panel-lovelace.ts b/src/panels/lovelace/ha-panel-lovelace.ts index 8b4cf33945e2..2ccca5e5d244 100644 --- a/src/panels/lovelace/ha-panel-lovelace.ts +++ b/src/panels/lovelace/ha-panel-lovelace.ts @@ -459,3 +459,9 @@ export class LovelacePanel extends LitElement { } } } + +declare global { + interface HTMLElementTagNameMap { + "ha-panel-lovelace": LovelacePanel; + } +} diff --git a/src/panels/lovelace/strategies/original-states-dashboard-strategy.ts b/src/panels/lovelace/strategies/original-states-dashboard-strategy.ts index 86f010d9a49e..0c7ae3c14f1f 100644 --- a/src/panels/lovelace/strategies/original-states-dashboard-strategy.ts +++ b/src/panels/lovelace/strategies/original-states-dashboard-strategy.ts @@ -33,3 +33,9 @@ export class OriginalStatesDashboardStrategy extends ReactiveElement { ); } } + +declare global { + interface HTMLElementTagNameMap { + "original-states-dashboard-strategy": OriginalStatesDashboardStrategy; + } +} diff --git a/src/panels/lovelace/strategies/original-states-view-strategy.ts b/src/panels/lovelace/strategies/original-states-view-strategy.ts index 9fcf20e974e3..386f953fcfcf 100644 --- a/src/panels/lovelace/strategies/original-states-view-strategy.ts +++ b/src/panels/lovelace/strategies/original-states-view-strategy.ts @@ -75,3 +75,9 @@ export class OriginalStatesViewStrategy extends ReactiveElement { return view; } } + +declare global { + interface HTMLElementTagNameMap { + "original-states-view-strategy": OriginalStatesViewStrategy; + } +} diff --git a/src/state-summary/state-card-update.ts b/src/state-summary/state-card-update.ts index fc307cb37227..85d34517a07b 100755 --- a/src/state-summary/state-card-update.ts +++ b/src/state-summary/state-card-update.ts @@ -54,3 +54,9 @@ export class StateCardUpdate extends LitElement { ]; } } + +declare global { + interface HTMLElementTagNameMap { + "state-card-update": StateCardUpdate; + } +} diff --git a/tsconfig.json b/tsconfig.json index 0a45a72573b1..81f29f08d90e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -29,7 +29,7 @@ "rules": { // Custom elements "no-unclosed-tag": "warning", - "no-missing-element-type-definition": "warning", + "no-missing-element-type-definition": "error", // Binding names "no-legacy-attribute": "error", // Binding types From 8583c879f2e2ecd4e76351d6154b4d4ef662c5a1 Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Tue, 9 Jan 2024 09:00:59 -0500 Subject: [PATCH 107/361] Fix invalid directive bindings (#19330) --- src/dialogs/generic/dialog-box.ts | 2 +- tsconfig.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/dialogs/generic/dialog-box.ts b/src/dialogs/generic/dialog-box.ts index 3b2ded7aad35..2660b5679971 100644 --- a/src/dialogs/generic/dialog-box.ts +++ b/src/dialogs/generic/dialog-box.ts @@ -74,7 +74,7 @@ class DialogBox extends LitElement { Date: Tue, 9 Jan 2024 09:02:15 -0500 Subject: [PATCH 108/361] Fix incompatible boolean property types (#19337) --- gallery/src/components/demo-black-white-row.ts | 2 +- gallery/src/components/demo-card.ts | 2 +- gallery/src/components/demo-more-info.ts | 2 +- src/components/chart/state-history-chart-timeline.ts | 2 +- src/components/chart/state-history-charts.ts | 2 +- src/components/entity/ha-state-label-badge.ts | 2 +- src/components/ha-assist-pipeline-picker.ts | 2 +- src/components/ha-date-range-picker.ts | 4 ++-- src/components/ha-labeled-slider.ts | 6 +++--- src/components/ha-menu-button.ts | 2 +- src/components/ha-theme-picker.ts | 2 +- src/panels/calendar/ha-recurrence-rule-editor.ts | 4 ++-- .../ha-config-application-credentials.ts | 4 ++-- src/panels/config/areas/ha-config-areas-dashboard.ts | 4 ++-- src/panels/config/areas/ha-config-areas.ts | 6 +++--- src/panels/config/automation/blueprint-automation-editor.ts | 2 +- src/panels/config/automation/ha-automation-editor.ts | 4 ++-- src/panels/config/automation/ha-config-automation.ts | 6 +++--- src/panels/config/blueprint/ha-config-blueprint.ts | 6 +++--- src/panels/config/cloud/ha-config-cloud.ts | 4 ++-- src/panels/config/dashboard/ha-config-dashboard.ts | 4 ++-- .../config/devices/device-detail/ha-device-entities-card.ts | 2 +- .../config/devices/device-detail/ha-device-info-card.ts | 2 +- .../integration-elements/mqtt/mqtt-discovery-payload.ts | 2 +- .../integration-elements/mqtt/mqtt-messages.ts | 4 ++-- src/panels/config/devices/ha-config-devices-dashboard.ts | 4 ++-- src/panels/config/devices/ha-config-devices.ts | 6 +++--- src/panels/config/ha-config-section.ts | 2 +- src/panels/config/ha-panel-config.ts | 2 +- src/panels/config/helpers/forms/ha-counter-form.ts | 2 +- src/panels/config/helpers/forms/ha-input_boolean-form.ts | 2 +- src/panels/config/helpers/forms/ha-input_button-form.ts | 2 +- src/panels/config/helpers/forms/ha-input_datetime-form.ts | 2 +- src/panels/config/helpers/forms/ha-input_number-form.ts | 2 +- src/panels/config/helpers/forms/ha-input_select-form.ts | 2 +- src/panels/config/helpers/forms/ha-input_text-form.ts | 2 +- src/panels/config/helpers/forms/ha-schedule-form.ts | 2 +- src/panels/config/helpers/forms/ha-timer-form.ts | 2 +- src/panels/config/helpers/ha-config-helpers.ts | 4 ++-- .../config/integrations/ha-config-integrations-dashboard.ts | 4 ++-- src/panels/config/integrations/ha-config-integrations.ts | 4 ++-- .../integration-panels/matter/matter-config-panel.ts | 4 ++-- .../integration-panels/zha/zha-cluster-commands.ts | 2 +- .../integration-panels/zha/zha-clusters-data-table.ts | 2 +- .../integration-panels/zha/zha-config-dashboard-router.ts | 4 ++-- .../integration-panels/zha/zha-manage-clusters.ts | 2 +- .../integration-panels/zwave_js/zwave_js-config-router.ts | 4 ++-- .../lovelace/dashboards/ha-config-lovelace-dashboards.ts | 4 ++-- src/panels/config/lovelace/ha-config-lovelace.ts | 4 ++-- .../lovelace/resources/ha-config-lovelace-resources.ts | 4 ++-- src/panels/config/person/ha-config-person.ts | 4 ++-- src/panels/config/scene/ha-config-scene.ts | 6 +++--- src/panels/config/scene/ha-scene-dashboard.ts | 4 ++-- src/panels/config/scene/ha-scene-editor.ts | 6 +++--- src/panels/config/script/ha-config-script.ts | 6 +++--- src/panels/config/script/ha-script-picker.ts | 4 ++-- src/panels/config/tags/ha-config-tags.ts | 4 ++-- .../ha-config-voice-assistants-assistants.ts | 4 ++-- .../config/voice-assistants/ha-config-voice-assistants.ts | 4 ++-- src/panels/config/zone/ha-config-zone.ts | 4 ++-- src/panels/custom/ha-panel-custom.ts | 2 +- src/panels/developer-tools/debug/ha-debug-connection-row.ts | 2 +- src/panels/developer-tools/developer-tools-router.ts | 2 +- src/panels/developer-tools/ha-panel-developer-tools.ts | 2 +- .../developer-tools/template/developer-tools-template.ts | 2 +- src/panels/lovelace/cards/hui-entity-filter-card.ts | 4 ++-- src/panels/lovelace/cards/hui-stack-card.ts | 2 +- src/panels/lovelace/components/hui-conditional-base.ts | 2 +- src/panels/lovelace/ha-panel-lovelace.ts | 2 +- src/panels/profile/ha-advanced-mode-row.ts | 2 +- src/panels/profile/ha-enable-shortcuts-row.ts | 2 +- src/panels/profile/ha-force-narrow-row.ts | 2 +- src/panels/profile/ha-pick-dashboard-row.ts | 2 +- src/panels/profile/ha-pick-date-format-row.ts | 2 +- src/panels/profile/ha-pick-first-weekday-row.ts | 2 +- src/panels/profile/ha-pick-language-row.ts | 2 +- src/panels/profile/ha-pick-number-format-row.ts | 2 +- src/panels/profile/ha-pick-time-format-row.ts | 2 +- src/panels/profile/ha-pick-time-zone-row.ts | 2 +- src/panels/profile/ha-push-notifications-row.ts | 2 +- src/panels/profile/ha-set-suspend-row.ts | 2 +- src/panels/profile/ha-set-vibrate-row.ts | 2 +- 82 files changed, 124 insertions(+), 124 deletions(-) diff --git a/gallery/src/components/demo-black-white-row.ts b/gallery/src/components/demo-black-white-row.ts index 43a58ea59e5b..30b2c533b762 100644 --- a/gallery/src/components/demo-black-white-row.ts +++ b/gallery/src/components/demo-black-white-row.ts @@ -11,7 +11,7 @@ class DemoBlackWhiteRow extends LitElement { @property() value!: any; - @property() disabled = false; + @property({ type: Boolean }) public disabled = false; protected render(): TemplateResult { return html` diff --git a/gallery/src/components/demo-card.ts b/gallery/src/components/demo-card.ts index 1c0879295204..b0ae74afdcab 100644 --- a/gallery/src/components/demo-card.ts +++ b/gallery/src/components/demo-card.ts @@ -15,7 +15,7 @@ class DemoCard extends LitElement { @property() public config!: DemoCardConfig; - @property() public showConfig = false; + @property({ type: Boolean }) public showConfig = false; @state() private _size?: number; diff --git a/gallery/src/components/demo-more-info.ts b/gallery/src/components/demo-more-info.ts index eeb5c9226465..5fb5fe502221 100644 --- a/gallery/src/components/demo-more-info.ts +++ b/gallery/src/components/demo-more-info.ts @@ -12,7 +12,7 @@ class DemoMoreInfo extends LitElement { @property() public entityId!: string; - @property() public showConfig!: boolean; + @property({ type: Boolean }) public showConfig = false; render() { const state = this._getState(this.entityId, this.hass.states); diff --git a/src/components/chart/state-history-chart-timeline.ts b/src/components/chart/state-history-chart-timeline.ts index d1c535e23cc4..4ed3eff474d3 100644 --- a/src/components/chart/state-history-chart-timeline.ts +++ b/src/components/chart/state-history-chart-timeline.ts @@ -23,7 +23,7 @@ export class StateHistoryChartTimeline extends LitElement { @property({ attribute: false }) public data: TimelineEntity[] = []; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public names?: Record; diff --git a/src/components/chart/state-history-charts.ts b/src/components/chart/state-history-charts.ts index 10bee3c74764..8c5736205477 100644 --- a/src/components/chart/state-history-charts.ts +++ b/src/components/chart/state-history-charts.ts @@ -52,7 +52,7 @@ export class StateHistoryCharts extends LitElement { @property({ attribute: false }) public historyData!: HistoryResult; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public names?: Record; diff --git a/src/components/entity/ha-state-label-badge.ts b/src/components/entity/ha-state-label-badge.ts index f735452b6e89..9460c68147f5 100644 --- a/src/components/entity/ha-state-label-badge.ts +++ b/src/components/entity/ha-state-label-badge.ts @@ -61,7 +61,7 @@ export class HaStateLabelBadge extends LitElement { @property() public image?: string; - @property() public showName?: boolean; + @property({ type: Boolean }) public showName = false; @state() private _timerTimeRemaining?: number; diff --git a/src/components/ha-assist-pipeline-picker.ts b/src/components/ha-assist-pipeline-picker.ts index 80a69b2d2799..d6cb6c30bbe5 100644 --- a/src/components/ha-assist-pipeline-picker.ts +++ b/src/components/ha-assist-pipeline-picker.ts @@ -31,7 +31,7 @@ export class HaAssistPipelinePicker extends LitElement { @property({ type: Boolean }) public required = false; - @property() public includeLastUsed = false; + @property({ type: Boolean }) public includeLastUsed = false; @state() _pipelines?: AssistPipeline[]; diff --git a/src/components/ha-date-range-picker.ts b/src/components/ha-date-range-picker.ts index 7e16fecd22db..00f2f1a9fe29 100644 --- a/src/components/ha-date-range-picker.ts +++ b/src/components/ha-date-range-picker.ts @@ -54,9 +54,9 @@ export class HaDateRangePicker extends LitElement { @state() private _ranges?: DateRangePickerRanges; - @property() public autoApply = false; + @property({ type: Boolean }) public autoApply = false; - @property() public timePicker = true; + @property({ type: Boolean }) public timePicker = true; @property({ type: Boolean }) public disabled = false; diff --git a/src/components/ha-labeled-slider.ts b/src/components/ha-labeled-slider.ts index 5faf7a8b96b2..9bbf0e95371d 100644 --- a/src/components/ha-labeled-slider.ts +++ b/src/components/ha-labeled-slider.ts @@ -6,7 +6,7 @@ import { fireEvent } from "../common/dom/fire_event"; @customElement("ha-labeled-slider") class HaLabeledSlider extends LitElement { - @property() public labeled? = false; + @property({ type: Boolean }) public labeled = false; @property() public caption?: string; @@ -22,7 +22,7 @@ class HaLabeledSlider extends LitElement { @property() public helper?: string; - @property() public extra = false; + @property({ type: Boolean }) public extra = false; @property() public icon?: string; @@ -38,7 +38,7 @@ class HaLabeledSlider extends LitElement { .min=${this.min} .max=${this.max} .step=${this.step} - labeled=${this.labeled} + .labeled=${this.labeled} .disabled=${this.disabled} .value=${this.value} @change=${this._inputChanged} diff --git a/src/components/ha-menu-button.ts b/src/components/ha-menu-button.ts index 0e7fac5aa390..63481ad1fd42 100644 --- a/src/components/ha-menu-button.ts +++ b/src/components/ha-menu-button.ts @@ -11,7 +11,7 @@ import "./ha-icon-button"; class HaMenuButton extends LitElement { @property({ type: Boolean }) public hassio = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property({ attribute: false }) public hass!: HomeAssistant; diff --git a/src/components/ha-theme-picker.ts b/src/components/ha-theme-picker.ts index 104c327cad4f..425b1a7227c6 100644 --- a/src/components/ha-theme-picker.ts +++ b/src/components/ha-theme-picker.ts @@ -21,7 +21,7 @@ export class HaThemePicker extends LitElement { @property() public label?: string; - @property() includeDefault?: boolean = false; + @property({ type: Boolean }) includeDefault = false; @property({ attribute: false }) public hass?: HomeAssistant; diff --git a/src/panels/calendar/ha-recurrence-rule-editor.ts b/src/panels/calendar/ha-recurrence-rule-editor.ts index d7f19d0b671b..7a131e23d856 100644 --- a/src/panels/calendar/ha-recurrence-rule-editor.ts +++ b/src/panels/calendar/ha-recurrence-rule-editor.ts @@ -35,13 +35,13 @@ import { export class RecurrenceRuleEditor extends LitElement { @property() public hass!: HomeAssistant; - @property() public disabled = false; + @property({ type: Boolean }) public disabled = false; @property() public value = ""; @property() public dtstart?: Date; - @property() public allDay?: boolean; + @property({ type: Boolean }) public allDay = false; @property({ attribute: false }) public locale!: HomeAssistant["locale"]; diff --git a/src/panels/config/application_credentials/ha-config-application-credentials.ts b/src/panels/config/application_credentials/ha-config-application-credentials.ts index d42f57f3f9ef..6752532e2922 100644 --- a/src/panels/config/application_credentials/ha-config-application-credentials.ts +++ b/src/panels/config/application_credentials/ha-config-application-credentials.ts @@ -41,9 +41,9 @@ export class HaConfigApplicationCredentials extends LitElement { @state() public _applicationCredentials: ApplicationCredential[] = []; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/config/areas/ha-config-areas-dashboard.ts b/src/panels/config/areas/ha-config-areas-dashboard.ts index 3623d585571b..62c3a047439c 100644 --- a/src/panels/config/areas/ha-config-areas-dashboard.ts +++ b/src/panels/config/areas/ha-config-areas-dashboard.ts @@ -36,9 +36,9 @@ import { export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public isWide?: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/config/areas/ha-config-areas.ts b/src/panels/config/areas/ha-config-areas.ts index c5508eccfb9a..fd8959f050e2 100644 --- a/src/panels/config/areas/ha-config-areas.ts +++ b/src/panels/config/areas/ha-config-areas.ts @@ -11,11 +11,11 @@ import "./ha-config-areas-dashboard"; class HaConfigAreas extends HassRouterPage { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public showAdvanced!: boolean; + @property({ type: Boolean }) public showAdvanced = false; protected routerOptions: RouterOptions = { defaultPage: "dashboard", diff --git a/src/panels/config/automation/blueprint-automation-editor.ts b/src/panels/config/automation/blueprint-automation-editor.ts index 3f5a8ea65012..9f9e6c4e0824 100644 --- a/src/panels/config/automation/blueprint-automation-editor.ts +++ b/src/panels/config/automation/blueprint-automation-editor.ts @@ -24,7 +24,7 @@ import "../ha-config-section"; export class HaBlueprintAutomationEditor extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; @property({ type: Boolean }) public disabled = false; diff --git a/src/panels/config/automation/ha-automation-editor.ts b/src/panels/config/automation/ha-automation-editor.ts index c8ca54c3d7ee..a4f6f2ef3ed5 100644 --- a/src/panels/config/automation/ha-automation-editor.ts +++ b/src/panels/config/automation/ha-automation-editor.ts @@ -89,9 +89,9 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) { @property() public automations!: AutomationEntity[]; - @property() public isWide?: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/config/automation/ha-config-automation.ts b/src/panels/config/automation/ha-config-automation.ts index 1af2b4cadc1c..ef1182e98205 100644 --- a/src/panels/config/automation/ha-config-automation.ts +++ b/src/panels/config/automation/ha-config-automation.ts @@ -24,11 +24,11 @@ const equal = (a: AutomationEntity[], b: AutomationEntity[]): boolean => { class HaConfigAutomation extends HassRouterPage { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public showAdvanced!: boolean; + @property({ type: Boolean }) public showAdvanced = false; @property() public automations: AutomationEntity[] = []; diff --git a/src/panels/config/blueprint/ha-config-blueprint.ts b/src/panels/config/blueprint/ha-config-blueprint.ts index 68f50c94b4fa..1e6bbeed95b3 100644 --- a/src/panels/config/blueprint/ha-config-blueprint.ts +++ b/src/panels/config/blueprint/ha-config-blueprint.ts @@ -19,11 +19,11 @@ declare global { class HaConfigBlueprint extends HassRouterPage { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public showAdvanced!: boolean; + @property({ type: Boolean }) public showAdvanced = false; @property() public blueprints: Record = {}; diff --git a/src/panels/config/cloud/ha-config-cloud.ts b/src/panels/config/cloud/ha-config-cloud.ts index c48600fc3ea5..53d70fb7b973 100644 --- a/src/panels/config/cloud/ha-config-cloud.ts +++ b/src/panels/config/cloud/ha-config-cloud.ts @@ -16,9 +16,9 @@ const NOT_LOGGED_IN_URLS = ["login", "register", "forgot-password"]; class HaConfigCloud extends HassRouterPage { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/config/dashboard/ha-config-dashboard.ts b/src/panels/config/dashboard/ha-config-dashboard.ts index 2ed6a9bb8f2c..f1f1e5ba7e05 100644 --- a/src/panels/config/dashboard/ha-config-dashboard.ts +++ b/src/panels/config/dashboard/ha-config-dashboard.ts @@ -117,11 +117,11 @@ class HaConfigDashboard extends SubscribeMixin(LitElement) { @property({ type: Boolean, reflect: true }) public narrow!: boolean; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; @property() public cloudStatus?: CloudStatus; - @property() public showAdvanced!: boolean; + @property({ type: Boolean }) public showAdvanced = false; @state() private _tip?: string; diff --git a/src/panels/config/devices/device-detail/ha-device-entities-card.ts b/src/panels/config/devices/device-detail/ha-device-entities-card.ts index fb5aad023e97..9de2c1e69aa3 100644 --- a/src/panels/config/devices/device-detail/ha-device-entities-card.ts +++ b/src/panels/config/devices/device-detail/ha-device-entities-card.ts @@ -40,7 +40,7 @@ export class HaDeviceEntitiesCard extends LitElement { @property() public entities!: EntityRegistryStateEntry[]; - @property() public showHidden = false; + @property({ type: Boolean }) public showHidden = false; @state() private _extDisabledEntityEntries?: Record< string, diff --git a/src/panels/config/devices/device-detail/ha-device-info-card.ts b/src/panels/config/devices/device-detail/ha-device-info-card.ts index 524e57534a0a..0ec966058607 100644 --- a/src/panels/config/devices/device-detail/ha-device-info-card.ts +++ b/src/panels/config/devices/device-detail/ha-device-info-card.ts @@ -15,7 +15,7 @@ export class HaDeviceCard extends LitElement { @property() public device!: DeviceRegistryEntry; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render(): TemplateResult { return html` diff --git a/src/panels/config/devices/device-detail/integration-elements/mqtt/mqtt-discovery-payload.ts b/src/panels/config/devices/device-detail/integration-elements/mqtt/mqtt-discovery-payload.ts index cb5e8e3b8469..f61c1995f3cc 100644 --- a/src/panels/config/devices/device-detail/integration-elements/mqtt/mqtt-discovery-payload.ts +++ b/src/panels/config/devices/device-detail/integration-elements/mqtt/mqtt-discovery-payload.ts @@ -7,7 +7,7 @@ import { classMap } from "lit/directives/class-map"; class MQTTDiscoveryPayload extends LitElement { @property() public payload!: Record; - @property() public showAsYaml = false; + @property({ type: Boolean }) public showAsYaml = false; @property() public summary!: string; diff --git a/src/panels/config/devices/device-detail/integration-elements/mqtt/mqtt-messages.ts b/src/panels/config/devices/device-detail/integration-elements/mqtt/mqtt-messages.ts index 2d3b5acd1fb4..31386b94021d 100644 --- a/src/panels/config/devices/device-detail/integration-elements/mqtt/mqtt-messages.ts +++ b/src/panels/config/devices/device-detail/integration-elements/mqtt/mqtt-messages.ts @@ -14,9 +14,9 @@ class MQTTMessages extends LitElement { @property() public direction!: string; - @property() public showAsYaml = false; + @property({ type: Boolean }) public showAsYaml = false; - @property() public showDeserialized = false; + @property({ type: Boolean }) public showDeserialized = false; @property() public subscribedTopic!: string; diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts index ca7c4fde9847..400c0baf31a7 100644 --- a/src/panels/config/devices/ha-config-devices-dashboard.ts +++ b/src/panels/config/devices/ha-config-devices-dashboard.ts @@ -62,9 +62,9 @@ interface DeviceRowData extends DeviceRegistryEntry { export class HaConfigDeviceDashboard extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow = false; + @property({ type: Boolean }) public narrow = false; - @property() public isWide = false; + @property({ type: Boolean }) public isWide = false; @property() public entries!: ConfigEntry[]; diff --git a/src/panels/config/devices/ha-config-devices.ts b/src/panels/config/devices/ha-config-devices.ts index 8b3329cec1fa..bfda9129cb51 100644 --- a/src/panels/config/devices/ha-config-devices.ts +++ b/src/panels/config/devices/ha-config-devices.ts @@ -16,11 +16,11 @@ import "./ha-config-devices-dashboard"; class HaConfigDevices extends HassRouterPage { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public showAdvanced!: boolean; + @property({ type: Boolean }) public showAdvanced = false; protected routerOptions: RouterOptions = { defaultPage: "dashboard", diff --git a/src/panels/config/ha-config-section.ts b/src/panels/config/ha-config-section.ts index 37ab1808a033..cf6088be9fc1 100644 --- a/src/panels/config/ha-config-section.ts +++ b/src/panels/config/ha-config-section.ts @@ -4,7 +4,7 @@ import { classMap } from "lit/directives/class-map"; @customElement("ha-config-section") export class HaConfigSection extends LitElement { - @property() public isWide = false; + @property({ type: Boolean }) public isWide = false; @property({ type: Boolean }) public vertical = false; diff --git a/src/panels/config/ha-panel-config.ts b/src/panels/config/ha-panel-config.ts index ff4b4d4504f7..d8a26d529689 100644 --- a/src/panels/config/ha-panel-config.ts +++ b/src/panels/config/ha-panel-config.ts @@ -360,7 +360,7 @@ export const configSections: { [name: string]: PageNavigation[] } = { class HaPanelConfig extends SubscribeMixin(HassRouterPage) { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/config/helpers/forms/ha-counter-form.ts b/src/panels/config/helpers/forms/ha-counter-form.ts index 479abac63360..8f49d421c19a 100644 --- a/src/panels/config/helpers/forms/ha-counter-form.ts +++ b/src/panels/config/helpers/forms/ha-counter-form.ts @@ -13,7 +13,7 @@ import { HomeAssistant } from "../../../../types"; class HaCounterForm extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public new?: boolean; + @property({ type: Boolean }) public new = false; private _item?: Partial; diff --git a/src/panels/config/helpers/forms/ha-input_boolean-form.ts b/src/panels/config/helpers/forms/ha-input_boolean-form.ts index 870d83cf22ae..8a2c1eeacd8c 100644 --- a/src/panels/config/helpers/forms/ha-input_boolean-form.ts +++ b/src/panels/config/helpers/forms/ha-input_boolean-form.ts @@ -11,7 +11,7 @@ import { HomeAssistant } from "../../../../types"; class HaInputBooleanForm extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public new?: boolean; + @property({ type: Boolean }) public new = false; private _item?: InputBoolean; diff --git a/src/panels/config/helpers/forms/ha-input_button-form.ts b/src/panels/config/helpers/forms/ha-input_button-form.ts index 0b8ec14edeb6..940931175704 100644 --- a/src/panels/config/helpers/forms/ha-input_button-form.ts +++ b/src/panels/config/helpers/forms/ha-input_button-form.ts @@ -11,7 +11,7 @@ import { HomeAssistant } from "../../../../types"; class HaInputButtonForm extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public new?: boolean; + @property({ type: Boolean }) public new = false; @state() private _name!: string; diff --git a/src/panels/config/helpers/forms/ha-input_datetime-form.ts b/src/panels/config/helpers/forms/ha-input_datetime-form.ts index 76e3eac39923..dfb3dd65035d 100644 --- a/src/panels/config/helpers/forms/ha-input_datetime-form.ts +++ b/src/panels/config/helpers/forms/ha-input_datetime-form.ts @@ -14,7 +14,7 @@ import { HomeAssistant } from "../../../../types"; class HaInputDateTimeForm extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public new?: boolean; + @property({ type: Boolean }) public new = false; private _item?: InputDateTime; diff --git a/src/panels/config/helpers/forms/ha-input_number-form.ts b/src/panels/config/helpers/forms/ha-input_number-form.ts index 0c83b7861cdb..b047708d240f 100644 --- a/src/panels/config/helpers/forms/ha-input_number-form.ts +++ b/src/panels/config/helpers/forms/ha-input_number-form.ts @@ -14,7 +14,7 @@ import { HomeAssistant } from "../../../../types"; class HaInputNumberForm extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public new?: boolean; + @property({ type: Boolean }) public new = false; private _item?: Partial; diff --git a/src/panels/config/helpers/forms/ha-input_select-form.ts b/src/panels/config/helpers/forms/ha-input_select-form.ts index 69c328f2a0b4..4f5ed4c27176 100644 --- a/src/panels/config/helpers/forms/ha-input_select-form.ts +++ b/src/panels/config/helpers/forms/ha-input_select-form.ts @@ -20,7 +20,7 @@ import type { HomeAssistant } from "../../../../types"; class HaInputSelectForm extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public new?: boolean; + @property({ type: Boolean }) public new = false; private _item?: InputSelect; diff --git a/src/panels/config/helpers/forms/ha-input_text-form.ts b/src/panels/config/helpers/forms/ha-input_text-form.ts index 90252e2ab0d1..852b62d628c6 100644 --- a/src/panels/config/helpers/forms/ha-input_text-form.ts +++ b/src/panels/config/helpers/forms/ha-input_text-form.ts @@ -15,7 +15,7 @@ import { HomeAssistant } from "../../../../types"; class HaInputTextForm extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public new?: boolean; + @property({ type: Boolean }) public new = false; private _item?: InputText; diff --git a/src/panels/config/helpers/forms/ha-schedule-form.ts b/src/panels/config/helpers/forms/ha-schedule-form.ts index a1c08c083e6b..a4dd69bf4571 100644 --- a/src/panels/config/helpers/forms/ha-schedule-form.ts +++ b/src/panels/config/helpers/forms/ha-schedule-form.ts @@ -44,7 +44,7 @@ const defaultFullCalendarConfig: CalendarOptions = { class HaScheduleForm extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public new?: boolean; + @property({ type: Boolean }) public new = false; @state() private _name!: string; diff --git a/src/panels/config/helpers/forms/ha-timer-form.ts b/src/panels/config/helpers/forms/ha-timer-form.ts index 4108f7fa43b4..34ff52ad87f2 100644 --- a/src/panels/config/helpers/forms/ha-timer-form.ts +++ b/src/panels/config/helpers/forms/ha-timer-form.ts @@ -11,7 +11,7 @@ import { HomeAssistant } from "../../../../types"; class HaTimerForm extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public new?: boolean; + @property({ type: Boolean }) public new = false; private _item?: Timer; diff --git a/src/panels/config/helpers/ha-config-helpers.ts b/src/panels/config/helpers/ha-config-helpers.ts index 1982716efc61..f755092c7f4c 100644 --- a/src/panels/config/helpers/ha-config-helpers.ts +++ b/src/panels/config/helpers/ha-config-helpers.ts @@ -81,9 +81,9 @@ const getConfigEntry = ( export class HaConfigHelpers extends SubscribeMixin(LitElement) { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/config/integrations/ha-config-integrations-dashboard.ts b/src/panels/config/integrations/ha-config-integrations-dashboard.ts index ed2b52ce04e9..ded9e80b9884 100644 --- a/src/panels/config/integrations/ha-config-integrations-dashboard.ts +++ b/src/panels/config/integrations/ha-config-integrations-dashboard.ts @@ -94,9 +94,9 @@ class HaConfigIntegrationsDashboard extends SubscribeMixin(LitElement) { @property({ type: Boolean, reflect: true }) public narrow!: boolean; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public showAdvanced!: boolean; + @property({ type: Boolean }) public showAdvanced = false; @property() public route!: Route; diff --git a/src/panels/config/integrations/ha-config-integrations.ts b/src/panels/config/integrations/ha-config-integrations.ts index 42ff9330b44d..212427e492c3 100644 --- a/src/panels/config/integrations/ha-config-integrations.ts +++ b/src/panels/config/integrations/ha-config-integrations.ts @@ -53,9 +53,9 @@ class HaConfigIntegrations extends SubscribeMixin(HassRouterPage) { @property({ type: Boolean, reflect: true }) public narrow!: boolean; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public showAdvanced!: boolean; + @property({ type: Boolean }) public showAdvanced = false; protected routerOptions: RouterOptions = { defaultPage: "dashboard", diff --git a/src/panels/config/integrations/integration-panels/matter/matter-config-panel.ts b/src/panels/config/integrations/integration-panels/matter/matter-config-panel.ts index e6aa5b102f33..22a11152c9d1 100644 --- a/src/panels/config/integrations/integration-panels/matter/matter-config-panel.ts +++ b/src/panels/config/integrations/integration-panels/matter/matter-config-panel.ts @@ -24,9 +24,9 @@ export const configTabs: PageNavigation[] = [ class MatterConfigRouter extends HassRouterPage { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected routerOptions: RouterOptions = { defaultPage: "dashboard", diff --git a/src/panels/config/integrations/integration-panels/zha/zha-cluster-commands.ts b/src/panels/config/integrations/integration-panels/zha/zha-cluster-commands.ts index a63bc9e75d97..66e59c382d1c 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-cluster-commands.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-cluster-commands.ts @@ -28,7 +28,7 @@ import { IssueCommandServiceData } from "./types"; export class ZHAClusterCommands extends LitElement { @property({ attribute: false }) public hass?: HomeAssistant; - @property() public isWide?: boolean; + @property({ type: Boolean }) public isWide = false; @property() public device?: ZHADevice; diff --git a/src/panels/config/integrations/integration-panels/zha/zha-clusters-data-table.ts b/src/panels/config/integrations/integration-panels/zha/zha-clusters-data-table.ts index bf45ceecbf19..1ceb7b2cb02d 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-clusters-data-table.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-clusters-data-table.ts @@ -20,7 +20,7 @@ export interface ClusterRowData extends Cluster { export class ZHAClustersDataTable extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow = false; + @property({ type: Boolean }) public narrow = false; @property() public clusters: Cluster[] = []; diff --git a/src/panels/config/integrations/integration-panels/zha/zha-config-dashboard-router.ts b/src/panels/config/integrations/integration-panels/zha/zha-config-dashboard-router.ts index 758f8acf0e8d..f3104c8a71eb 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-config-dashboard-router.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-config-dashboard-router.ts @@ -10,9 +10,9 @@ import { HomeAssistant } from "../../../../../types"; class ZHAConfigDashboardRouter extends HassRouterPage { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; private _configEntry = new URLSearchParams(window.location.search).get( "config_entry" diff --git a/src/panels/config/integrations/integration-panels/zha/zha-manage-clusters.ts b/src/panels/config/integrations/integration-panels/zha/zha-manage-clusters.ts index 65512ab1a2f1..cdc2deb0cd90 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-manage-clusters.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-manage-clusters.ts @@ -40,7 +40,7 @@ const tabs = ["attributes", "commands"] as const; export class ZHAManageClusters extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public isWide?: boolean; + @property({ type: Boolean }) public isWide = false; @property() public device?: ZHADevice; diff --git a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-config-router.ts b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-config-router.ts index a8be9fa857b3..15dba45a433f 100644 --- a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-config-router.ts +++ b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-config-router.ts @@ -26,9 +26,9 @@ export const configTabs: PageNavigation[] = [ class ZWaveJSConfigRouter extends HassRouterPage { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; private _configEntry = new URLSearchParams(window.location.search).get( "config_entry" diff --git a/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts b/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts index de05a5a0d6af..24a48a6c6821 100644 --- a/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts +++ b/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts @@ -56,9 +56,9 @@ type DataTableItem = Pick< export class HaConfigLovelaceDashboards extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/config/lovelace/ha-config-lovelace.ts b/src/panels/config/lovelace/ha-config-lovelace.ts index 727438f3b6dc..c494232bb865 100644 --- a/src/panels/config/lovelace/ha-config-lovelace.ts +++ b/src/panels/config/lovelace/ha-config-lovelace.ts @@ -19,9 +19,9 @@ export const lovelaceTabs = [ class HaConfigLovelace extends HassRouterPage { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; protected routerOptions: RouterOptions = { defaultPage: "dashboards", diff --git a/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts b/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts index 71df3c3354da..5dbab9dfed27 100644 --- a/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts +++ b/src/panels/config/lovelace/resources/ha-config-lovelace-resources.ts @@ -41,9 +41,9 @@ import { showResourceDetailDialog } from "./show-dialog-lovelace-resource-detail export class HaConfigLovelaceRescources extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/config/person/ha-config-person.ts b/src/panels/config/person/ha-config-person.ts index 60311cd901eb..96d60fe92f49 100644 --- a/src/panels/config/person/ha-config-person.ts +++ b/src/panels/config/person/ha-config-person.ts @@ -35,9 +35,9 @@ import { export class HaConfigPerson extends LitElement { @property({ attribute: false }) public hass?: HomeAssistant; - @property() public isWide?: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow?: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/config/scene/ha-config-scene.ts b/src/panels/config/scene/ha-config-scene.ts index ae0742e754f1..59a88b92c24a 100644 --- a/src/panels/config/scene/ha-config-scene.ts +++ b/src/panels/config/scene/ha-config-scene.ts @@ -24,11 +24,11 @@ const equal = (a: SceneEntity[], b: SceneEntity[]): boolean => { class HaConfigScene extends HassRouterPage { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public showAdvanced!: boolean; + @property({ type: Boolean }) public showAdvanced = false; @property() public scenes: SceneEntity[] = []; diff --git a/src/panels/config/scene/ha-scene-dashboard.ts b/src/panels/config/scene/ha-scene-dashboard.ts index 0d3f9a7a0561..e6bc9476f1ca 100644 --- a/src/panels/config/scene/ha-scene-dashboard.ts +++ b/src/panels/config/scene/ha-scene-dashboard.ts @@ -64,9 +64,9 @@ type SceneItem = SceneEntity & { class HaSceneDashboard extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; @property() public route!: Route; diff --git a/src/panels/config/scene/ha-scene-editor.ts b/src/panels/config/scene/ha-scene-editor.ts index da9817835151..5814ac7fd650 100644 --- a/src/panels/config/scene/ha-scene-editor.ts +++ b/src/panels/config/scene/ha-scene-editor.ts @@ -87,9 +87,9 @@ export class HaSceneEditor extends SubscribeMixin( ) { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; @property() public route!: Route; @@ -97,7 +97,7 @@ export class HaSceneEditor extends SubscribeMixin( @property() public scenes!: SceneEntity[]; - @property() public showAdvanced!: boolean; + @property({ type: Boolean }) public showAdvanced = false; @state() private _dirty = false; diff --git a/src/panels/config/script/ha-config-script.ts b/src/panels/config/script/ha-config-script.ts index 45ff779f9123..3e96240f7a37 100644 --- a/src/panels/config/script/ha-config-script.ts +++ b/src/panels/config/script/ha-config-script.ts @@ -27,11 +27,11 @@ const equal = (a: ScriptEntity[], b: ScriptEntity[]): boolean => { class HaConfigScript extends HassRouterPage { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public showAdvanced!: boolean; + @property({ type: Boolean }) public showAdvanced = false; @property() public scripts: ScriptEntity[] = []; diff --git a/src/panels/config/script/ha-script-picker.ts b/src/panels/config/script/ha-script-picker.ts index ac2ace77675e..82e369b9e0c4 100644 --- a/src/panels/config/script/ha-script-picker.ts +++ b/src/panels/config/script/ha-script-picker.ts @@ -70,9 +70,9 @@ class HaScriptPicker extends LitElement { @property() public scripts!: ScriptEntity[]; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/config/tags/ha-config-tags.ts b/src/panels/config/tags/ha-config-tags.ts index 5eb80452e232..493bdf402410 100644 --- a/src/panels/config/tags/ha-config-tags.ts +++ b/src/panels/config/tags/ha-config-tags.ts @@ -44,9 +44,9 @@ export interface TagRowData extends Tag { export class HaConfigTags extends SubscribeMixin(LitElement) { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/config/voice-assistants/ha-config-voice-assistants-assistants.ts b/src/panels/config/voice-assistants/ha-config-voice-assistants-assistants.ts index c932806fa89b..918af55d23c2 100644 --- a/src/panels/config/voice-assistants/ha-config-voice-assistants-assistants.ts +++ b/src/panels/config/voice-assistants/ha-config-voice-assistants-assistants.ts @@ -27,9 +27,9 @@ export class HaConfigVoiceAssistantsAssistants extends LitElement { ExposeEntitySettings >; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/config/voice-assistants/ha-config-voice-assistants.ts b/src/panels/config/voice-assistants/ha-config-voice-assistants.ts index dd827fcfe043..4c94317ca760 100644 --- a/src/panels/config/voice-assistants/ha-config-voice-assistants.ts +++ b/src/panels/config/voice-assistants/ha-config-voice-assistants.ts @@ -33,9 +33,9 @@ class HaConfigVoiceAssistants extends HassRouterPage { @property({ attribute: false }) public cloudStatus!: CloudStatus; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; - @property() public isWide!: boolean; + @property({ type: Boolean }) public isWide = false; @state() @consume({ context: entitiesContext, subscribe: true }) diff --git a/src/panels/config/zone/ha-config-zone.ts b/src/panels/config/zone/ha-config-zone.ts index cbe1af87ddce..6869293fb8bf 100644 --- a/src/panels/config/zone/ha-config-zone.ts +++ b/src/panels/config/zone/ha-config-zone.ts @@ -52,9 +52,9 @@ import { showZoneDetailDialog } from "./show-dialog-zone-detail"; export class HaConfigZone extends SubscribeMixin(LitElement) { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public isWide?: boolean; + @property({ type: Boolean }) public isWide = false; - @property() public narrow?: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/custom/ha-panel-custom.ts b/src/panels/custom/ha-panel-custom.ts index 9d685a18932e..975c5cff76f2 100644 --- a/src/panels/custom/ha-panel-custom.ts +++ b/src/panels/custom/ha-panel-custom.ts @@ -23,7 +23,7 @@ declare global { export class HaPanelCustom extends ReactiveElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route!: Route; diff --git a/src/panels/developer-tools/debug/ha-debug-connection-row.ts b/src/panels/developer-tools/debug/ha-debug-connection-row.ts index e4b1c5c3ff9b..764931f649a8 100644 --- a/src/panels/developer-tools/debug/ha-debug-connection-row.ts +++ b/src/panels/developer-tools/debug/ha-debug-connection-row.ts @@ -10,7 +10,7 @@ import { storeState } from "../../../util/ha-pref-storage"; class HaDebugConnectionRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render(): TemplateResult { return html` diff --git a/src/panels/developer-tools/developer-tools-router.ts b/src/panels/developer-tools/developer-tools-router.ts index a205fa810dd1..6fdf6aa01080 100644 --- a/src/panels/developer-tools/developer-tools-router.ts +++ b/src/panels/developer-tools/developer-tools-router.ts @@ -6,7 +6,7 @@ import { HomeAssistant } from "../../types"; class DeveloperToolsRouter extends HassRouterPage { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected routerOptions: RouterOptions = { // defaultPage: "info", diff --git a/src/panels/developer-tools/ha-panel-developer-tools.ts b/src/panels/developer-tools/ha-panel-developer-tools.ts index de7ec5777c11..12fe04725a33 100644 --- a/src/panels/developer-tools/ha-panel-developer-tools.ts +++ b/src/panels/developer-tools/ha-panel-developer-tools.ts @@ -19,7 +19,7 @@ class PanelDeveloperTools extends LitElement { @property() public route!: Route; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected firstUpdated(changedProps) { super.firstUpdated(changedProps); diff --git a/src/panels/developer-tools/template/developer-tools-template.ts b/src/panels/developer-tools/template/developer-tools-template.ts index 734dff2ff461..0f6abb854ef3 100644 --- a/src/panels/developer-tools/template/developer-tools-template.ts +++ b/src/panels/developer-tools/template/developer-tools-template.ts @@ -41,7 +41,7 @@ For loop example getting entity values in the weather domain: class HaPanelDevTemplate extends LitElement { @property() public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @state() private _error?: string; diff --git a/src/panels/lovelace/cards/hui-entity-filter-card.ts b/src/panels/lovelace/cards/hui-entity-filter-card.ts index 797d7114a74b..a18026e24fcf 100644 --- a/src/panels/lovelace/cards/hui-entity-filter-card.ts +++ b/src/panels/lovelace/cards/hui-entity-filter-card.ts @@ -42,9 +42,9 @@ export class HuiEntityFilterCard @property({ attribute: false }) public hass?: HomeAssistant; - @property() public isPanel = false; + @property({ type: Boolean }) public isPanel = false; - @property() public editMode = false; + @property({ type: Boolean }) public editMode = false; @state() private _config?: EntityFilterCardConfig; diff --git a/src/panels/lovelace/cards/hui-stack-card.ts b/src/panels/lovelace/cards/hui-stack-card.ts index dafda696dc0e..604797c21915 100644 --- a/src/panels/lovelace/cards/hui-stack-card.ts +++ b/src/panels/lovelace/cards/hui-stack-card.ts @@ -28,7 +28,7 @@ export abstract class HuiStackCard @property({ attribute: false }) public hass?: HomeAssistant; - @property() public editMode?: boolean; + @property({ type: Boolean }) public editMode = false; @property() protected _cards?: LovelaceCard[]; diff --git a/src/panels/lovelace/components/hui-conditional-base.ts b/src/panels/lovelace/components/hui-conditional-base.ts index 3ffa839fdd7e..a66a4a2e3a31 100644 --- a/src/panels/lovelace/components/hui-conditional-base.ts +++ b/src/panels/lovelace/components/hui-conditional-base.ts @@ -31,7 +31,7 @@ function extractMediaQueries( export class HuiConditionalBase extends ReactiveElement { @property({ attribute: false }) public hass?: HomeAssistant; - @property() public editMode?: boolean; + @property({ type: Boolean }) public editMode = false; @property() protected _config?: ConditionalCardConfig | ConditionalRowConfig; diff --git a/src/panels/lovelace/ha-panel-lovelace.ts b/src/panels/lovelace/ha-panel-lovelace.ts index 2ccca5e5d244..eb367df99e19 100644 --- a/src/panels/lovelace/ha-panel-lovelace.ts +++ b/src/panels/lovelace/ha-panel-lovelace.ts @@ -56,7 +56,7 @@ export class LovelacePanel extends LitElement { @property({ attribute: false }) public hass?: HomeAssistant; - @property() public narrow?: boolean; + @property({ type: Boolean }) public narrow = false; @property() public route?: Route; diff --git a/src/panels/profile/ha-advanced-mode-row.ts b/src/panels/profile/ha-advanced-mode-row.ts index ce0c9ec50fad..3eed30ceed52 100644 --- a/src/panels/profile/ha-advanced-mode-row.ts +++ b/src/panels/profile/ha-advanced-mode-row.ts @@ -13,7 +13,7 @@ import { HomeAssistant } from "../../types"; class AdvancedModeRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @property() public coreUserData?: CoreFrontendUserData; diff --git a/src/panels/profile/ha-enable-shortcuts-row.ts b/src/panels/profile/ha-enable-shortcuts-row.ts index 429c439c698d..4d2c54d1bfef 100644 --- a/src/panels/profile/ha-enable-shortcuts-row.ts +++ b/src/panels/profile/ha-enable-shortcuts-row.ts @@ -10,7 +10,7 @@ import type { HomeAssistant } from "../../types"; class HaEnableShortcutsRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render(): TemplateResult { return html` diff --git a/src/panels/profile/ha-force-narrow-row.ts b/src/panels/profile/ha-force-narrow-row.ts index 771f49c7d9cb..e42002e9f33b 100644 --- a/src/panels/profile/ha-force-narrow-row.ts +++ b/src/panels/profile/ha-force-narrow-row.ts @@ -10,7 +10,7 @@ import type { HomeAssistant } from "../../types"; class HaForcedNarrowRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render(): TemplateResult { return html` diff --git a/src/panels/profile/ha-pick-dashboard-row.ts b/src/panels/profile/ha-pick-dashboard-row.ts index eebac9fe47e3..a94fb594d8be 100644 --- a/src/panels/profile/ha-pick-dashboard-row.ts +++ b/src/panels/profile/ha-pick-dashboard-row.ts @@ -14,7 +14,7 @@ import { HomeAssistant } from "../../types"; class HaPickDashboardRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; @state() private _dashboards?: LovelaceDashboard[]; diff --git a/src/panels/profile/ha-pick-date-format-row.ts b/src/panels/profile/ha-pick-date-format-row.ts index ec4e1dae7cb7..500ab75d5736 100644 --- a/src/panels/profile/ha-pick-date-format-row.ts +++ b/src/panels/profile/ha-pick-date-format-row.ts @@ -13,7 +13,7 @@ import { HomeAssistant } from "../../types"; class DateFormatRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render(): TemplateResult { const date = new Date(); diff --git a/src/panels/profile/ha-pick-first-weekday-row.ts b/src/panels/profile/ha-pick-first-weekday-row.ts index 6a615cc43326..aca53ca9d6a9 100644 --- a/src/panels/profile/ha-pick-first-weekday-row.ts +++ b/src/panels/profile/ha-pick-first-weekday-row.ts @@ -12,7 +12,7 @@ import { HomeAssistant } from "../../types"; class FirstWeekdayRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render(): TemplateResult { return html` diff --git a/src/panels/profile/ha-pick-language-row.ts b/src/panels/profile/ha-pick-language-row.ts index 1ee3074b0967..44fc5de54ab0 100644 --- a/src/panels/profile/ha-pick-language-row.ts +++ b/src/panels/profile/ha-pick-language-row.ts @@ -9,7 +9,7 @@ import { HomeAssistant } from "../../types"; export class HaPickLanguageRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render() { return html` diff --git a/src/panels/profile/ha-pick-number-format-row.ts b/src/panels/profile/ha-pick-number-format-row.ts index 6c9a739dd7e7..18f9f140505d 100644 --- a/src/panels/profile/ha-pick-number-format-row.ts +++ b/src/panels/profile/ha-pick-number-format-row.ts @@ -13,7 +13,7 @@ import { HomeAssistant } from "../../types"; class NumberFormatRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render(): TemplateResult { return html` diff --git a/src/panels/profile/ha-pick-time-format-row.ts b/src/panels/profile/ha-pick-time-format-row.ts index b9d24d597f3e..fa4ddcbe9567 100644 --- a/src/panels/profile/ha-pick-time-format-row.ts +++ b/src/panels/profile/ha-pick-time-format-row.ts @@ -13,7 +13,7 @@ import { HomeAssistant } from "../../types"; class TimeFormatRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render(): TemplateResult { const date = new Date(); diff --git a/src/panels/profile/ha-pick-time-zone-row.ts b/src/panels/profile/ha-pick-time-zone-row.ts index c1bd070406c3..06ab7ffa1ea8 100644 --- a/src/panels/profile/ha-pick-time-zone-row.ts +++ b/src/panels/profile/ha-pick-time-zone-row.ts @@ -13,7 +13,7 @@ import { HomeAssistant } from "../../types"; class TimeZoneRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render(): TemplateResult { const date = new Date(); diff --git a/src/panels/profile/ha-push-notifications-row.ts b/src/panels/profile/ha-push-notifications-row.ts index 92b2fc546f4c..a02f02347c4a 100644 --- a/src/panels/profile/ha-push-notifications-row.ts +++ b/src/panels/profile/ha-push-notifications-row.ts @@ -10,7 +10,7 @@ import { HomeAssistant } from "../../types"; class HaPushNotificationsRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render(): TemplateResult { const platformLoaded = isComponentLoaded(this.hass, "notify.html5"); diff --git a/src/panels/profile/ha-set-suspend-row.ts b/src/panels/profile/ha-set-suspend-row.ts index 47a4d7f431ba..332e9fe6d974 100644 --- a/src/panels/profile/ha-set-suspend-row.ts +++ b/src/panels/profile/ha-set-suspend-row.ts @@ -23,7 +23,7 @@ declare global { class HaSetSuspendRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render(): TemplateResult { return html` diff --git a/src/panels/profile/ha-set-vibrate-row.ts b/src/panels/profile/ha-set-vibrate-row.ts index 184b9b096f6b..a55769d4c5a3 100644 --- a/src/panels/profile/ha-set-vibrate-row.ts +++ b/src/panels/profile/ha-set-vibrate-row.ts @@ -11,7 +11,7 @@ import type { HomeAssistant } from "../../types"; class HaSetVibrateRow extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public narrow!: boolean; + @property({ type: Boolean }) public narrow = false; protected render(): TemplateResult { return html` From 88abeada44666e9edde84e2b3a021f16dadbb13d Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Tue, 9 Jan 2024 09:06:50 -0500 Subject: [PATCH 109/361] Remove Intl polyfill on connection and consistently resolve time zone (#19326) --- src/common/datetime/format_date.ts | 25 ++++++++++--------- src/common/datetime/format_date_time.ts | 9 ++++--- src/common/datetime/format_time.ts | 9 ++++--- src/common/datetime/localize_date.ts | 1 + src/common/datetime/resolve-time-zone.ts | 15 +++++++++++ src/onboarding/onboarding-core-config.ts | 4 +-- .../calendar/dialog-calendar-event-detail.ts | 7 ++++-- .../calendar/dialog-calendar-event-editor.ts | 12 ++++----- .../config/core/ha-config-section-general.ts | 5 +--- src/panels/profile/ha-pick-time-zone-row.ts | 8 +++--- src/panels/todo/dialog-todo-item-editor.ts | 10 ++++---- src/state/connection-mixin.ts | 12 +-------- 12 files changed, 63 insertions(+), 54 deletions(-) create mode 100644 src/common/datetime/resolve-time-zone.ts diff --git a/src/common/datetime/format_date.ts b/src/common/datetime/format_date.ts index 5f94177db045..2369eb46b608 100644 --- a/src/common/datetime/format_date.ts +++ b/src/common/datetime/format_date.ts @@ -1,7 +1,8 @@ import { HassConfig } from "home-assistant-js-websocket"; import memoizeOne from "memoize-one"; -import { FrontendLocaleData, DateFormat } from "../../data/translation"; +import { DateFormat, FrontendLocaleData } from "../../data/translation"; import "../../resources/intl-polyfill"; +import { resolveTimeZone } from "./resolve-time-zone"; // Tuesday, August 10 export const formatDateWeekdayDay = ( @@ -16,7 +17,7 @@ const formatDateWeekdayDayMem = memoizeOne( weekday: "long", month: "long", day: "numeric", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -33,7 +34,7 @@ const formatDateMem = memoizeOne( year: "numeric", month: "long", day: "numeric", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -50,7 +51,7 @@ const formatDateShortMem = memoizeOne( year: "numeric", month: "short", day: "numeric", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -105,7 +106,7 @@ const formatDateNumericMem = memoizeOne( year: "numeric", month: "numeric", day: "numeric", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }); } @@ -113,7 +114,7 @@ const formatDateNumericMem = memoizeOne( year: "numeric", month: "numeric", day: "numeric", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }); } ); @@ -130,7 +131,7 @@ const formatDateVeryShortMem = memoizeOne( new Intl.DateTimeFormat(locale.language, { day: "numeric", month: "short", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -146,7 +147,7 @@ const formatDateMonthYearMem = memoizeOne( new Intl.DateTimeFormat(locale.language, { month: "long", year: "numeric", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -161,7 +162,7 @@ const formatDateMonthMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { month: "long", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -176,7 +177,7 @@ const formatDateYearMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { year: "numeric", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -191,7 +192,7 @@ const formatDateWeekdayMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { weekday: "long", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -206,6 +207,6 @@ const formatDateWeekdayShortMem = memoizeOne( (locale: FrontendLocaleData, serverTimeZone: string) => new Intl.DateTimeFormat(locale.language, { weekday: "short", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); diff --git a/src/common/datetime/format_date_time.ts b/src/common/datetime/format_date_time.ts index 52700b4a2344..76a32e1accc1 100644 --- a/src/common/datetime/format_date_time.ts +++ b/src/common/datetime/format_date_time.ts @@ -4,6 +4,7 @@ import { FrontendLocaleData } from "../../data/translation"; import "../../resources/intl-polyfill"; import { formatDateNumeric } from "./format_date"; import { formatTime } from "./format_time"; +import { resolveTimeZone } from "./resolve-time-zone"; import { useAmPm } from "./use_am_pm"; // August 9, 2021, 8:23 AM @@ -22,7 +23,7 @@ const formatDateTimeMem = memoizeOne( hour: useAmPm(locale) ? "numeric" : "2-digit", minute: "2-digit", hourCycle: useAmPm(locale) ? "h12" : "h23", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -42,7 +43,7 @@ const formatShortDateTimeWithYearMem = memoizeOne( hour: useAmPm(locale) ? "numeric" : "2-digit", minute: "2-digit", hourCycle: useAmPm(locale) ? "h12" : "h23", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -61,7 +62,7 @@ const formatShortDateTimeMem = memoizeOne( hour: useAmPm(locale) ? "numeric" : "2-digit", minute: "2-digit", hourCycle: useAmPm(locale) ? "h12" : "h23", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -82,7 +83,7 @@ const formatDateTimeWithSecondsMem = memoizeOne( minute: "2-digit", second: "2-digit", hourCycle: useAmPm(locale) ? "h12" : "h23", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); diff --git a/src/common/datetime/format_time.ts b/src/common/datetime/format_time.ts index 948eb553fea4..ed3e6b603d29 100644 --- a/src/common/datetime/format_time.ts +++ b/src/common/datetime/format_time.ts @@ -2,6 +2,7 @@ import { HassConfig } from "home-assistant-js-websocket"; import memoizeOne from "memoize-one"; import { FrontendLocaleData } from "../../data/translation"; import "../../resources/intl-polyfill"; +import { resolveTimeZone } from "./resolve-time-zone"; import { useAmPm } from "./use_am_pm"; // 9:15 PM || 21:15 @@ -17,7 +18,7 @@ const formatTimeMem = memoizeOne( hour: "numeric", minute: "2-digit", hourCycle: useAmPm(locale) ? "h12" : "h23", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -35,7 +36,7 @@ const formatTimeWithSecondsMem = memoizeOne( minute: "2-digit", second: "2-digit", hourCycle: useAmPm(locale) ? "h12" : "h23", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -53,7 +54,7 @@ const formatTimeWeekdayMem = memoizeOne( hour: useAmPm(locale) ? "numeric" : "2-digit", minute: "2-digit", hourCycle: useAmPm(locale) ? "h12" : "h23", - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); @@ -71,6 +72,6 @@ const formatTime24hMem = memoizeOne( hour: "numeric", minute: "2-digit", hour12: false, - timeZone: locale.time_zone === "server" ? serverTimeZone : undefined, + timeZone: resolveTimeZone(locale.time_zone, serverTimeZone), }) ); diff --git a/src/common/datetime/localize_date.ts b/src/common/datetime/localize_date.ts index 428261801d58..9fa851d7c293 100644 --- a/src/common/datetime/localize_date.ts +++ b/src/common/datetime/localize_date.ts @@ -1,4 +1,5 @@ import memoizeOne from "memoize-one"; +import "../../resources/intl-polyfill"; export const localizeWeekdays = memoizeOne( (language: string, short: boolean): string[] => { diff --git a/src/common/datetime/resolve-time-zone.ts b/src/common/datetime/resolve-time-zone.ts new file mode 100644 index 000000000000..d085edac6abc --- /dev/null +++ b/src/common/datetime/resolve-time-zone.ts @@ -0,0 +1,15 @@ +import { TimeZone } from "../../data/translation"; + +// Browser time zone can be determined from Intl, with fallback to UTC for polyfill or no support. +// Alternatively, we could fallback to a fixed offset IANA zone (e.g. "Etc/GMT+5") using +// Date.prototype.getTimeOffset(), but IANA only has whole hour Etc zones, and problems +// might occur with relative time due to DST. +// Use optional chain instead of polyfill import since polyfill will always return UTC +export const LOCAL_TIME_ZONE = + Intl.DateTimeFormat?.().resolvedOptions?.().timeZone ?? "UTC"; + +// Pick time zone based on user profile option. Core zone is used when local cannot be determined. +export const resolveTimeZone = (option: TimeZone, serverTimeZone: string) => + option === TimeZone.local && LOCAL_TIME_ZONE !== "UTC" + ? LOCAL_TIME_ZONE + : serverTimeZone; diff --git a/src/onboarding/onboarding-core-config.ts b/src/onboarding/onboarding-core-config.ts index 61cdad8d01e0..73debff9cb40 100644 --- a/src/onboarding/onboarding-core-config.ts +++ b/src/onboarding/onboarding-core-config.ts @@ -9,6 +9,7 @@ import { TemplateResult, } from "lit"; import { customElement, property, state } from "lit/decorators"; +import { LOCAL_TIME_ZONE } from "../common/datetime/resolve-time-zone"; import { fireEvent } from "../common/dom/fire_event"; import type { LocalizeFunc } from "../common/translations/localize"; import "../components/ha-alert"; @@ -33,8 +34,7 @@ class OnboardingCoreConfig extends LitElement { private _elevation = "0"; - private _timeZone: ConfigUpdateValues["time_zone"] = - Intl.DateTimeFormat?.().resolvedOptions?.().timeZone; + private _timeZone: ConfigUpdateValues["time_zone"] = LOCAL_TIME_ZONE; private _language: ConfigUpdateValues["language"] = getLocalLanguage(); diff --git a/src/panels/calendar/dialog-calendar-event-detail.ts b/src/panels/calendar/dialog-calendar-event-detail.ts index 5962aa83f147..fc07fea31f34 100644 --- a/src/panels/calendar/dialog-calendar-event-detail.ts +++ b/src/panels/calendar/dialog-calendar-event-detail.ts @@ -25,6 +25,7 @@ import { renderRRuleAsText } from "./recurrence"; import { showConfirmEventDialog } from "./show-confirm-event-dialog-box"; import { CalendarEventDetailDialogParams } from "./show-dialog-calendar-event-detail"; import { showCalendarEventEditDialog } from "./show-dialog-calendar-event-editor"; +import { resolveTimeZone } from "../../common/datetime/resolve-time-zone"; class DialogCalendarEventDetail extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -138,8 +139,10 @@ class DialogCalendarEventDetail extends LitElement { } private _formatDateRange() { - // Parse a dates in the browser timezone - const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; + const timeZone = resolveTimeZone( + this.hass.locale.time_zone, + this.hass.config.time_zone + ); const start = toDate(this._data!.dtstart, { timeZone: timeZone }); const endValue = toDate(this._data!.dtend, { timeZone: timeZone }); // All day events should be displayed as a day earlier diff --git a/src/panels/calendar/dialog-calendar-event-editor.ts b/src/panels/calendar/dialog-calendar-event-editor.ts index e1db40da695d..377f4ef65f57 100644 --- a/src/panels/calendar/dialog-calendar-event-editor.ts +++ b/src/panels/calendar/dialog-calendar-event-editor.ts @@ -11,6 +11,7 @@ import { HassEntity } from "home-assistant-js-websocket"; import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; +import { resolveTimeZone } from "../../common/datetime/resolve-time-zone"; import { fireEvent } from "../../common/dom/fire_event"; import { computeStateDomain } from "../../common/entity/compute_state_domain"; import { supportsFeature } from "../../common/entity/supports-feature"; @@ -32,7 +33,6 @@ import { deleteCalendarEvent, updateCalendarEvent, } from "../../data/calendar"; -import { TimeZone } from "../../data/translation"; import { haStyleDialog } from "../../resources/styles"; import { HomeAssistant } from "../../types"; import "../lovelace/components/hui-generic-entity-row"; @@ -68,7 +68,7 @@ class DialogCalendarEventEditor extends LitElement { @state() private _submitting = false; - // Dates are manipulated and displayed in the browser timezone + // Dates are displayed in the timezone according to the user's profile // which may be different from the Home Assistant timezone. When // events are persisted, they are relative to the Home Assistant // timezone, but floating without a timezone. @@ -85,10 +85,10 @@ class DialogCalendarEventEditor extends LitElement { computeStateDomain(stateObj) === "calendar" && supportsFeature(stateObj, CalendarEntityFeature.CREATE_EVENT) )?.entity_id; - this._timeZone = - this.hass.locale.time_zone === TimeZone.local - ? Intl.DateTimeFormat().resolvedOptions().timeZone - : this.hass.config.time_zone; + this._timeZone = resolveTimeZone( + this.hass.locale.time_zone, + this.hass.config.time_zone + ); if (params.entry) { const entry = params.entry!; this._allDay = isDate(entry.dtstart); diff --git a/src/panels/config/core/ha-config-section-general.ts b/src/panels/config/core/ha-config-section-general.ts index 22df34f25cfb..eb6681a26ac3 100644 --- a/src/panels/config/core/ha-config-section-general.ts +++ b/src/panels/config/core/ha-config-section-general.ts @@ -294,10 +294,7 @@ class HaConfigSectionGeneral extends LitElement { this._country = this.hass.config.country; this._language = this.hass.config.language; this._elevation = this.hass.config.elevation; - this._timeZone = - this.hass.config.time_zone || - Intl.DateTimeFormat?.().resolvedOptions?.().timeZone || - "Etc/GMT"; + this._timeZone = this.hass.config.time_zone || "Etc/GMT"; this._name = this.hass.config.location_name; this._updateUnits = true; } diff --git a/src/panels/profile/ha-pick-time-zone-row.ts b/src/panels/profile/ha-pick-time-zone-row.ts index 06ab7ffa1ea8..ef732bec1a6b 100644 --- a/src/panels/profile/ha-pick-time-zone-row.ts +++ b/src/panels/profile/ha-pick-time-zone-row.ts @@ -2,6 +2,7 @@ import "@material/mwc-list/mwc-list-item"; import { html, LitElement, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators"; import { formatDateTimeNumeric } from "../../common/datetime/format_date_time"; +import { resolveTimeZone } from "../../common/datetime/resolve-time-zone"; import { fireEvent } from "../../common/dom/fire_event"; import "../../components/ha-card"; import "../../components/ha-select"; @@ -48,10 +49,9 @@ class TimeZoneRow extends LitElement { >${this.hass.localize( `ui.panel.profile.time_zone.options.${format}`, { - timezone: (format === "server" - ? this.hass.config.time_zone - : Intl.DateTimeFormat?.().resolvedOptions?.().timeZone || - "" + timezone: resolveTimeZone( + format, + this.hass.config.time_zone ).replace("_", " "), } )}>( } this._updateHass({ areas }); }); - subscribeConfig(conn, (config) => { - if (this.hass?.config?.time_zone !== config.time_zone) { - import("../resources/intl-polyfill").then(() => { - if ("__setDefaultTimeZone" in Intl.DateTimeFormat) { - // @ts-ignore - Intl.DateTimeFormat.__setDefaultTimeZone(config.time_zone); - } - }); - } - this._updateHass({ config }); - }); + subscribeConfig(conn, (config) => this._updateHass({ config })); subscribeServices(conn, (services) => this._updateHass({ services })); subscribePanels(conn, (panels) => this._updateHass({ panels })); subscribeFrontendUserData(conn, "core", (userData) => From e8c1a34f3bb14ed09075dde2585bf40bcda9614d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 15:20:51 +0100 Subject: [PATCH 110/361] Update typescript-eslint monorepo to v6.18.0 (#19341) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 4 +- yarn.lock | 104 +++++++++++++++++++++++++-------------------------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/package.json b/package.json index dc36dcc68d9b..d9f58c9e1bbc 100644 --- a/package.json +++ b/package.json @@ -183,8 +183,8 @@ "@types/tar": "6.1.10", "@types/ua-parser-js": "0.7.39", "@types/webspeechapi": "0.0.29", - "@typescript-eslint/eslint-plugin": "6.17.0", - "@typescript-eslint/parser": "6.17.0", + "@typescript-eslint/eslint-plugin": "6.18.0", + "@typescript-eslint/parser": "6.18.0", "@web/dev-server": "0.1.38", "@web/dev-server-rollup": "0.4.1", "babel-loader": "9.1.3", diff --git a/yarn.lock b/yarn.lock index b008f90c71f4..4bf267a7a978 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4525,15 +4525,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.17.0" +"@typescript-eslint/eslint-plugin@npm:6.18.0": + version: 6.18.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.18.0" dependencies: "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:6.17.0" - "@typescript-eslint/type-utils": "npm:6.17.0" - "@typescript-eslint/utils": "npm:6.17.0" - "@typescript-eslint/visitor-keys": "npm:6.17.0" + "@typescript-eslint/scope-manager": "npm:6.18.0" + "@typescript-eslint/type-utils": "npm:6.18.0" + "@typescript-eslint/utils": "npm:6.18.0" + "@typescript-eslint/visitor-keys": "npm:6.18.0" debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" ignore: "npm:^5.2.4" @@ -4546,44 +4546,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: f2a5774e9cc03e491a5a488501e5622c7eebd766f5a4fc2c30642864a3b89b0807946bde33a678f326ba7032f3f6a51aa0bf9c2d10adc823804fc9fb47db55a6 + checksum: 7810a84f6d9cb735f6848aa4a7ef64c77740812afc0248fda63ec182910a1d045cd9a32d8e49b0e5323266db6da12a2fe50171147927b3186815a56f12c16ee7 languageName: node linkType: hard -"@typescript-eslint/parser@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/parser@npm:6.17.0" +"@typescript-eslint/parser@npm:6.18.0": + version: 6.18.0 + resolution: "@typescript-eslint/parser@npm:6.18.0" dependencies: - "@typescript-eslint/scope-manager": "npm:6.17.0" - "@typescript-eslint/types": "npm:6.17.0" - "@typescript-eslint/typescript-estree": "npm:6.17.0" - "@typescript-eslint/visitor-keys": "npm:6.17.0" + "@typescript-eslint/scope-manager": "npm:6.18.0" + "@typescript-eslint/types": "npm:6.18.0" + "@typescript-eslint/typescript-estree": "npm:6.18.0" + "@typescript-eslint/visitor-keys": "npm:6.18.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 2ed0ed4a5b30e953430ce3279df3655af09fa1caed2abf11804d239717daefc32a22864f6620ef57bb9c684c74a99a13241384fea5096e961385e3678fc2e920 + checksum: 6798332819f839454a8405e31cfaa0fe908d5966be929bef55e78ac51a0ff3868feb42b38e7772cedf88277f6b2841b3d91f6c573eacb945e2741ecae94047c7 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/scope-manager@npm:6.17.0" +"@typescript-eslint/scope-manager@npm:6.18.0": + version: 6.18.0 + resolution: "@typescript-eslint/scope-manager@npm:6.18.0" dependencies: - "@typescript-eslint/types": "npm:6.17.0" - "@typescript-eslint/visitor-keys": "npm:6.17.0" - checksum: fe09c628553c9336e6a36d32c1d34e78ebd20aa02130a6bf535329621ba5a98aaac171f607bc6e4d17b3478c42e7de6476376636897ce3f227c754eb99acd07e + "@typescript-eslint/types": "npm:6.18.0" + "@typescript-eslint/visitor-keys": "npm:6.18.0" + checksum: c2c465e6803f78d3300142167a8a79dd2613c64cf464a40a9cf6b13a2c10c3d82ca30bb9c2d26aba7f054b8740b38e1d25f377fcdf917aba489d5b5ea2550858 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/type-utils@npm:6.17.0" +"@typescript-eslint/type-utils@npm:6.18.0": + version: 6.18.0 + resolution: "@typescript-eslint/type-utils@npm:6.18.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:6.17.0" - "@typescript-eslint/utils": "npm:6.17.0" + "@typescript-eslint/typescript-estree": "npm:6.18.0" + "@typescript-eslint/utils": "npm:6.18.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.0.1" peerDependencies: @@ -4591,23 +4591,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: dc7938429193acfda61b7282197ec046039e2c4da41cdcddf4daaf300d10229e4e23bb0fcf0503b19c0b99a874849c8a9f5bb35ce106260f56a14106d2b41d8c + checksum: 9f4a392fe7b7f6b1fb02acbdaa331e764775f6404c29ca66774419e39552523d878227020526ca9c438d997555a99600f8d711496e9a435fb14a779e25ed094e languageName: node linkType: hard -"@typescript-eslint/types@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/types@npm:6.17.0" - checksum: 87ab1b5a3270ab34b917c22a2fb90a9ad7d9f3b19d73a337bc9efbe65f924da13482c97e8ccbe3bd3d081aa96039eeff50de41c1da2a2128066429b931cdb21d +"@typescript-eslint/types@npm:6.18.0": + version: 6.18.0 + resolution: "@typescript-eslint/types@npm:6.18.0" + checksum: fc507ca7a1bfec04467087165ff6722f7b9aa9a089ecf0c17656824a951b92ca014766e480122de850057c63a3066628985eb0681c5bbb80ab41d94e7bb52288 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.17.0" +"@typescript-eslint/typescript-estree@npm:6.18.0": + version: 6.18.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.18.0" dependencies: - "@typescript-eslint/types": "npm:6.17.0" - "@typescript-eslint/visitor-keys": "npm:6.17.0" + "@typescript-eslint/types": "npm:6.18.0" + "@typescript-eslint/visitor-keys": "npm:6.18.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" @@ -4617,34 +4617,34 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 1671b0d2f2fdf07074fb1e2524d61935cec173bd8db6e482cc5b2dcc77aed3ffa831396736ffa0ee2fdbddd8585ae9ca8d6c97bcaea1385b23907a1ec0508f83 + checksum: b65392e944baba97ed98e99a1e7122b7b05fa0d9a082b48d0190b377ae9e2ae4ed72d505a2f0f05f2ca78908f0e4b0f1acd44d345c7f4f4415fcec6bb2c57791 languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/utils@npm:6.17.0" +"@typescript-eslint/utils@npm:6.18.0": + version: 6.18.0 + resolution: "@typescript-eslint/utils@npm:6.18.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" "@types/json-schema": "npm:^7.0.12" "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:6.17.0" - "@typescript-eslint/types": "npm:6.17.0" - "@typescript-eslint/typescript-estree": "npm:6.17.0" + "@typescript-eslint/scope-manager": "npm:6.18.0" + "@typescript-eslint/types": "npm:6.18.0" + "@typescript-eslint/typescript-estree": "npm:6.18.0" semver: "npm:^7.5.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 37c63afcf66124bf84808699997953b8c84a378aa2c490a771b611d82cdac8499c58fac8eeb8378528e97660b59563d99297bfec4b982cd68760b0ffe54aa714 + checksum: f91798069e337ed42b7e415aabded833d540dab9adf66ae88183003428892584946f20a5496aae2dc65fc0f65b66496baed785a3470ee782b6e2dd25b9200c6c languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.17.0": - version: 6.17.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.17.0" +"@typescript-eslint/visitor-keys@npm:6.18.0": + version: 6.18.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.18.0" dependencies: - "@typescript-eslint/types": "npm:6.17.0" + "@typescript-eslint/types": "npm:6.18.0" eslint-visitor-keys: "npm:^3.4.1" - checksum: a2aed0e1437fdab8858ab9c7c8e355f8b72a5fa4b0adc54f28b8a2bbc29d4bb93214968ee940f83d013d0a4b83d00cd4eeeb05fb4c2c7d0ead324c6793f7d6d4 + checksum: bf34a357549d515607c761f385b7c7c82aaa07795cada0be2e1e3860c5103fbf731408ac07eaeb0517b51426d77ef9b194dfb94f205c776107a46e0d0027b452 languageName: node linkType: hard @@ -9571,8 +9571,8 @@ __metadata: "@types/tar": "npm:6.1.10" "@types/ua-parser-js": "npm:0.7.39" "@types/webspeechapi": "npm:0.0.29" - "@typescript-eslint/eslint-plugin": "npm:6.17.0" - "@typescript-eslint/parser": "npm:6.17.0" + "@typescript-eslint/eslint-plugin": "npm:6.18.0" + "@typescript-eslint/parser": "npm:6.18.0" "@vaadin/combo-box": "npm:24.3.2" "@vaadin/vaadin-themable-mixin": "npm:24.3.2" "@vibrant/color": "npm:3.2.1-alpha.1" From a5630a4a7d118950b2f44de331a463610e0f7b71 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Tue, 9 Jan 2024 16:15:33 +0100 Subject: [PATCH 111/361] Use switch for valve in entity row (#19342) --- src/components/entity/ha-entity-toggle.ts | 3 ++ .../entity-rows/hui-valve-entity-row.ts | 48 ++++++++++--------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/components/entity/ha-entity-toggle.ts b/src/components/entity/ha-entity-toggle.ts index ba1da0e6a9c4..21530a8a4cfc 100644 --- a/src/components/entity/ha-entity-toggle.ts +++ b/src/components/entity/ha-entity-toggle.ts @@ -129,6 +129,9 @@ export class HaEntityToggle extends LitElement { } else if (stateDomain === "cover") { serviceDomain = "cover"; service = turnOn ? "open_cover" : "close_cover"; + } else if (stateDomain === "valve") { + serviceDomain = "valve"; + service = turnOn ? "open_valve" : "close_valve"; } else if (stateDomain === "group") { serviceDomain = "homeassistant"; service = turnOn ? "turn_on" : "turn_off"; diff --git a/src/panels/lovelace/entity-rows/hui-valve-entity-row.ts b/src/panels/lovelace/entity-rows/hui-valve-entity-row.ts index 1d836e2ddb45..16e770b30c4e 100644 --- a/src/panels/lovelace/entity-rows/hui-valve-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-valve-entity-row.ts @@ -1,14 +1,7 @@ -import { - css, - CSSResultGroup, - html, - LitElement, - PropertyValues, - nothing, -} from "lit"; +import { LitElement, PropertyValues, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import "../../../components/ha-valve-controls"; -import { ValveEntity } from "../../../data/valve"; +import { isUnavailableState } from "../../../data/entity"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; @@ -37,7 +30,7 @@ class HuiValveEntityRow extends LitElement implements LovelaceRow { return nothing; } - const stateObj = this.hass.states[this._config.entity] as ValveEntity; + const stateObj = this.hass.states[this._config.entity]; if (!stateObj) { return html` @@ -47,23 +40,32 @@ class HuiValveEntityRow extends LitElement implements LovelaceRow { `; } + const showToggle = + stateObj.state === "open" || + stateObj.state === "closed" || + isUnavailableState(stateObj.state); + return html` - - + + ${showToggle + ? html` + + ` + : html` +
+ ${this.hass.formatEntityState(stateObj)} +
+ `}
`; } - - static get styles(): CSSResultGroup { - return css` - ha-valve-controls { - margin-right: -0.57em; - } - `; - } } declare global { From 6ab5116c34954dd7180c71658c345febdb27fd3c Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Wed, 10 Jan 2024 04:49:35 -0500 Subject: [PATCH 112/361] Fix incompatible number property types (#19349) --- src/components/chart/state-history-charts.ts | 2 +- src/components/ha-big-number.ts | 5 ++--- src/components/ha-labeled-slider.ts | 8 ++++---- src/components/ha-selector/ha-selector-boolean.ts | 2 +- src/components/ha-selector/ha-selector-number.ts | 4 ++-- src/state-summary/state-card-timer.ts | 2 +- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/components/chart/state-history-charts.ts b/src/components/chart/state-history-charts.ts index 8c5736205477..dd68187f3007 100644 --- a/src/components/chart/state-history-charts.ts +++ b/src/components/chart/state-history-charts.ts @@ -65,7 +65,7 @@ export class StateHistoryCharts extends LitElement { @property({ type: Boolean, attribute: "up-to-now" }) public upToNow = false; - @property() public hoursToShow?: number; + @property({ type: Number }) public hoursToShow?: number; @property({ type: Boolean }) public showNames = true; diff --git a/src/components/ha-big-number.ts b/src/components/ha-big-number.ts index 85a7783c87c1..48abfe232709 100644 --- a/src/components/ha-big-number.ts +++ b/src/components/ha-big-number.ts @@ -7,15 +7,14 @@ import { HomeAssistant } from "../types"; @customElement("ha-big-number") export class HaBigNumber extends LitElement { - @property() public value!: number; + @property({ type: Number }) public value!: number; @property() public unit?: string; @property({ attribute: "unit-position" }) public unitPosition: "top" | "bottom" = "top"; - @property({ attribute: false }) - public hass?: HomeAssistant; + @property({ attribute: false }) public hass?: HomeAssistant; @property({ attribute: false }) public formatOptions: Intl.NumberFormatOptions = {}; diff --git a/src/components/ha-labeled-slider.ts b/src/components/ha-labeled-slider.ts index 9bbf0e95371d..1c507a0c668d 100644 --- a/src/components/ha-labeled-slider.ts +++ b/src/components/ha-labeled-slider.ts @@ -14,11 +14,11 @@ class HaLabeledSlider extends LitElement { @property({ type: Boolean }) public required = true; - @property() public min: number = 0; + @property({ type: Number }) public min = 0; - @property() public max: number = 100; + @property({ type: Number }) public max = 100; - @property() public step: number = 1; + @property({ type: Number }) public step = 1; @property() public helper?: string; @@ -26,7 +26,7 @@ class HaLabeledSlider extends LitElement { @property() public icon?: string; - @property() public value?: number; + @property({ type: Number }) public value?: number; protected render() { return html` diff --git a/src/components/ha-selector/ha-selector-boolean.ts b/src/components/ha-selector/ha-selector-boolean.ts index d99f980d8bd1..0d94d6de7b22 100644 --- a/src/components/ha-selector/ha-selector-boolean.ts +++ b/src/components/ha-selector/ha-selector-boolean.ts @@ -10,7 +10,7 @@ import "../ha-input-helper-text"; export class HaBooleanSelector extends LitElement { @property() public hass!: HomeAssistant; - @property() public value?: number; + @property({ type: Boolean }) public value = false; @property() public label?: string; diff --git a/src/components/ha-selector/ha-selector-number.ts b/src/components/ha-selector/ha-selector-number.ts index 1d4d2b98d4d5..672e9f8a5270 100644 --- a/src/components/ha-selector/ha-selector-number.ts +++ b/src/components/ha-selector/ha-selector-number.ts @@ -14,9 +14,9 @@ export class HaNumberSelector extends LitElement { @property() public selector!: NumberSelector; - @property() public value?: number; + @property({ type: Number }) public value?: number; - @property() public placeholder?: number; + @property({ type: Number }) public placeholder?: number; @property() public label?: string; diff --git a/src/state-summary/state-card-timer.ts b/src/state-summary/state-card-timer.ts index 2279d20cd868..d746ba860cab 100644 --- a/src/state-summary/state-card-timer.ts +++ b/src/state-summary/state-card-timer.ts @@ -21,7 +21,7 @@ class StateCardTimer extends LitElement { @property({ type: Boolean }) public inDialog = false; - @property() public timeRemaining?: number; + @property({ type: Number }) public timeRemaining?: number; private _updateRemaining: any; From adb851a2b487d4230d856d5c3e490d5b45a4f2ca Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Wed, 10 Jan 2024 04:53:03 -0500 Subject: [PATCH 113/361] Fix unclosed HTML tags (#19343) * Fix unclosed HTML tags * Add missing import and remove unused class for debug tools * Remove div from debug page --- src/components/ha-label.ts | 10 ++--- .../mqtt/dialog-mqtt-device-debug-info.ts | 4 +- .../assist/developer-tools-assist.ts | 2 +- .../debug/developer-tools-debug.ts | 37 +++++++++---------- tsconfig.json | 1 - 5 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/components/ha-label.ts b/src/components/ha-label.ts index ffb4d0612649..dd0ed75d44a6 100644 --- a/src/components/ha-label.ts +++ b/src/components/ha-label.ts @@ -5,11 +5,11 @@ import { customElement } from "lit/decorators"; class HaLabel extends LitElement { protected render(): TemplateResult { return html` - - - -
- `; + + + + + `; } static get styles(): CSSResultGroup { diff --git a/src/panels/config/devices/device-detail/integration-elements/mqtt/dialog-mqtt-device-debug-info.ts b/src/panels/config/devices/device-detail/integration-elements/mqtt/dialog-mqtt-device-debug-info.ts index 790df95b6778..3600514238dd 100644 --- a/src/panels/config/devices/device-detail/integration-elements/mqtt/dialog-mqtt-device-debug-info.ts +++ b/src/panels/config/devices/device-detail/integration-elements/mqtt/dialog-mqtt-device-debug-info.ts @@ -181,7 +181,7 @@ class DialogMQTTDeviceDebugInfo extends LitElement { { n: topic.messages.length } )} > - + ` )} @@ -204,7 +204,7 @@ class DialogMQTTDeviceDebugInfo extends LitElement { { n: topic.messages.length } )} > - + ` )} diff --git a/src/panels/developer-tools/assist/developer-tools-assist.ts b/src/panels/developer-tools/assist/developer-tools-assist.ts index 7c3bdb35068a..de7e22c36b6b 100644 --- a/src/panels/developer-tools/assist/developer-tools-assist.ts +++ b/src/panels/developer-tools/assist/developer-tools-assist.ts @@ -165,7 +165,7 @@ class HaPanelDevAssist extends SubscribeMixin(LitElement) { ${this.hass.localize( "ui.panel.developer-tools.tabs.assist.download_results" )} - +
` : ""} diff --git a/src/panels/developer-tools/debug/developer-tools-debug.ts b/src/panels/developer-tools/debug/developer-tools-debug.ts index 6a5aa730cd9d..3d06c4d065db 100644 --- a/src/panels/developer-tools/debug/developer-tools-debug.ts +++ b/src/panels/developer-tools/debug/developer-tools-debug.ts @@ -1,5 +1,6 @@ -import { CSSResultGroup, LitElement, css, html } from "lit"; +import { LitElement, css, html } from "lit"; import { customElement, property } from "lit/decorators"; +import "../../../components/ha-card"; import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; @@ -18,31 +19,27 @@ class HaPanelDevDebug extends SubscribeMixin(LitElement) { .header=${this.hass.localize( "ui.panel.developer-tools.tabs.debug.title" )} - class="form" > -
- +
`; } - static get styles(): CSSResultGroup { - return [ - haStyle, - css` - .content { - padding: 28px 20px 16px; - display: block; - max-width: 600px; - margin: 0 auto; - } - `, - ]; - } + static styles = [ + haStyle, + css` + .content { + padding: 28px 20px 16px; + display: block; + max-width: 600px; + margin: 0 auto; + } + `, + ]; } declare global { diff --git a/tsconfig.json b/tsconfig.json index 3c9fb36ebc15..f54276cf0be9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -28,7 +28,6 @@ "strict": true, "rules": { // Custom elements - "no-unclosed-tag": "warning", "no-missing-element-type-definition": "error", // Binding names "no-legacy-attribute": "error", From 877c9b007b1324166f81256005c07b4f91445937 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 Jan 2024 07:33:15 -0500 Subject: [PATCH 114/361] Update dependency open to v10.0.3 (#19351) --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index d9f58c9e1bbc..89c6a5a839a1 100644 --- a/package.json +++ b/package.json @@ -222,7 +222,7 @@ "map-stream": "0.0.7", "mocha": "10.2.0", "object-hash": "3.0.0", - "open": "10.0.2", + "open": "10.0.3", "pinst": "3.0.0", "prettier": "3.1.1", "rollup": "2.79.1", diff --git a/yarn.lock b/yarn.lock index 4bf267a7a978..9f7aea707a17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9642,7 +9642,7 @@ __metadata: mocha: "npm:10.2.0" node-vibrant: "npm:3.2.1-alpha.1" object-hash: "npm:3.0.0" - open: "npm:10.0.2" + open: "npm:10.0.3" pinst: "npm:3.0.0" prettier: "npm:3.1.1" proxy-polyfill: "npm:0.3.2" @@ -12483,15 +12483,15 @@ __metadata: languageName: node linkType: hard -"open@npm:10.0.2": - version: 10.0.2 - resolution: "open@npm:10.0.2" +"open@npm:10.0.3": + version: 10.0.3 + resolution: "open@npm:10.0.3" dependencies: default-browser: "npm:^5.2.1" define-lazy-prop: "npm:^3.0.0" is-inside-container: "npm:^1.0.0" is-wsl: "npm:^3.1.0" - checksum: 6f7f9e08204af00930f2998690293df1a919a61c98b225ff9e3aa09a765254b8a98bec101644ffe991452c6aabea0c6f9e49670b559d48a44bfc5238f6b58351 + checksum: 4dc757ad1d3d63490822f991e9cbe3a7c05b7249fca2eaa571cb7d191e5cec88bc37e15d8ef4fd740d8989a288b661d8da253caa8d98e8c97430ddbbb0ae4ed1 languageName: node linkType: hard From 85beefec4c241833562930bdb3476eaf08177c19 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 10 Jan 2024 13:50:07 +0100 Subject: [PATCH 115/361] Fix logs, dont require advanced mode, allow provider in url and my (#19355) * Fix logs, dont require advanced mode, allow provider in url and my * Add params to my link with quick key `m` --- src/common/url/search-params.ts | 10 +++-- src/layouts/hass-subpage.ts | 1 - src/panels/config/logs/ha-config-logs.ts | 49 +++++++++++++++++++----- src/panels/my/ha-panel-my.ts | 3 ++ src/state/quick-bar-mixin.ts | 9 +++++ src/translations/en.json | 4 +- 6 files changed, 60 insertions(+), 16 deletions(-) diff --git a/src/common/url/search-params.ts b/src/common/url/search-params.ts index f4ebb347e8ea..a7bd025842a0 100644 --- a/src/common/url/search-params.ts +++ b/src/common/url/search-params.ts @@ -1,6 +1,8 @@ +import { mainWindow } from "../dom/get_main_window"; + export const extractSearchParamsObject = (): Record => { const query = {}; - const searchParams = new URLSearchParams(location.search); + const searchParams = new URLSearchParams(mainWindow.location.search); for (const [key, value] of searchParams.entries()) { query[key] = value; } @@ -8,7 +10,7 @@ export const extractSearchParamsObject = (): Record => { }; export const extractSearchParam = (param: string): string | null => { - const urlParams = new URLSearchParams(window.location.search); + const urlParams = new URLSearchParams(mainWindow.location.search); return urlParams.get(param); }; @@ -21,7 +23,7 @@ export const createSearchParam = (params: Record): string => { }; export const addSearchParam = (params: Record): string => { - const urlParams = new URLSearchParams(window.location.search); + const urlParams = new URLSearchParams(mainWindow.location.search); Object.entries(params).forEach(([key, value]) => { urlParams.set(key, value); }); @@ -29,7 +31,7 @@ export const addSearchParam = (params: Record): string => { }; export const removeSearchParam = (param: string): string => { - const urlParams = new URLSearchParams(window.location.search); + const urlParams = new URLSearchParams(mainWindow.location.search); urlParams.delete(param); return urlParams.toString(); }; diff --git a/src/layouts/hass-subpage.ts b/src/layouts/hass-subpage.ts index c0763b5790be..18483e218262 100644 --- a/src/layouts/hass-subpage.ts +++ b/src/layouts/hass-subpage.ts @@ -119,7 +119,6 @@ class HassSubpage extends LitElement { font-size: 20px; height: var(--header-height); padding: 8px 12px; - pointer-events: none; background-color: var(--app-header-background-color); font-weight: 400; color: var(--app-header-text-color, white); diff --git a/src/panels/config/logs/ha-config-logs.ts b/src/panels/config/logs/ha-config-logs.ts index 6d176fca5508..2ec2961b9a3c 100644 --- a/src/panels/config/logs/ha-config-logs.ts +++ b/src/panels/config/logs/ha-config-logs.ts @@ -14,6 +14,8 @@ import { HomeAssistant, Route } from "../../../types"; import "./error-log-card"; import "./system-log-card"; import type { SystemLogCard } from "./system-log-card"; +import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box"; +import { navigate } from "../../../common/navigate"; const logProviders: LogProvider[] = [ { @@ -50,13 +52,11 @@ export class HaConfigLogs extends LitElement { @property({ type: Boolean }) public isWide!: boolean; - @property({ type: Boolean }) public showAdvanced!: boolean; - @property({ attribute: false }) public route!: Route; @state() private _filter = extractSearchParam("filter") || ""; - @query("system-log-card", true) private systemLog?: SystemLogCard; + @query("system-log-card") private systemLog?: SystemLogCard; @state() private _selectedLogProvider = "core"; @@ -64,16 +64,15 @@ export class HaConfigLogs extends LitElement { public connectedCallback() { super.connectedCallback(); - if (this.systemLog && this.systemLog.loaded) { - this.systemLog.fetchData(); + const systemLog = this.systemLog; + if (systemLog && systemLog.loaded) { + systemLog.fetchData(); } } protected firstUpdated(changedProps): void { super.firstUpdated(changedProps); - if (isComponentLoaded(this.hass, "hassio")) { - this._getInstalledAddons(); - } + this._init(); } private async _filterChanged(ev) { @@ -111,8 +110,7 @@ export class HaConfigLogs extends LitElement { .header=${this.hass.localize("ui.panel.config.logs.caption")} back-path="/config/system" > - ${isComponentLoaded(this.hass, "hassio") && - this.hass.userData?.showAdvanced + ${isComponentLoaded(this.hass, "hassio") ? html` p.key === providerKey) + ) { + this._selectedLogProvider = providerKey; + } else { + showAlertDialog(this, { + title: + this.hass.localize("ui.panel.config.logs.provider_not_found") || + "Log provider not found", + text: this.hass.localize( + "ui.panel.config.logs.provider_not_available", + { + provider: + this._logProviders.find((p) => p.key === providerKey)?.name || + providerKey, + } + ), + }); + } + } } private async _getInstalledAddons() { @@ -209,6 +237,7 @@ export class HaConfigLogs extends LitElement { } search-input.header { --mdc-ripple-color: transparant; + margin-left: -16px; } .content { direction: ltr; diff --git a/src/panels/my/ha-panel-my.ts b/src/panels/my/ha-panel-my.ts index 55888fe09db5..c525fa2dee4d 100644 --- a/src/panels/my/ha-panel-my.ts +++ b/src/panels/my/ha-panel-my.ts @@ -189,6 +189,9 @@ export const getMyRedirects = (hasSupervisor: boolean): Redirects => ({ }, logs: { redirect: "/config/logs", + params: { + provider: "string?", + }, }, repairs: { component: "repairs", diff --git a/src/state/quick-bar-mixin.ts b/src/state/quick-bar-mixin.ts index f60cf0344f94..c1868f699d81 100644 --- a/src/state/quick-bar-mixin.ts +++ b/src/state/quick-bar-mixin.ts @@ -10,6 +10,7 @@ import { Constructor, HomeAssistant } from "../types"; import { storeState } from "../util/ha-pref-storage"; import { showToast } from "../util/toast"; import { HassElement } from "./hass-element"; +import { extractSearchParamsObject } from "../common/url/search-params"; declare global { interface HASSDomEvents { @@ -117,6 +118,14 @@ export default >(superClass: T) => )) { if (targetPath.startsWith(redirect.redirect)) { myParams.append("redirect", slug); + if (redirect.params) { + const params = extractSearchParamsObject(); + for (const key of Object.keys(redirect.params)) { + if (key in params) { + myParams.append(key, params[key]); + } + } + } window.open( `https://my.home-assistant.io/create-link/?${myParams.toString()}`, "_blank" diff --git a/src/translations/en.json b/src/translations/en.json index bd741720b336..adee4f24b8f4 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2157,7 +2157,9 @@ "custom_integration": "custom integration", "error_from_custom_integration": "This error originated from a custom integration.", "show_full_logs": "Show full logs", - "download_full_log": "Download full log" + "download_full_log": "Download full log", + "provider_not_found": "Log provider not found", + "provider_not_available": "Logs for ''{provider}'' are not available on your system." }, "lovelace": { "caption": "Dashboards", From de35e89c5880e4bf67b648b7c832d8ff1513fd6c Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 10 Jan 2024 15:21:54 +0100 Subject: [PATCH 116/361] Update ha-config-logs.ts --- src/panels/config/logs/ha-config-logs.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/panels/config/logs/ha-config-logs.ts b/src/panels/config/logs/ha-config-logs.ts index 2ec2961b9a3c..9ec02e0312df 100644 --- a/src/panels/config/logs/ha-config-logs.ts +++ b/src/panels/config/logs/ha-config-logs.ts @@ -182,6 +182,7 @@ export class HaConfigLogs extends LitElement { ) { this._selectedLogProvider = providerKey; } else { + navigate("/config/logs", { replace: true }); showAlertDialog(this, { title: this.hass.localize("ui.panel.config.logs.provider_not_found") || From a136fa687f37c6c6ae1835651556c15bc9521305 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 10 Jan 2024 06:22:59 -0800 Subject: [PATCH 117/361] Add page to list assist devices (#19301) * Add page to list assist devices * Translate title too --- src/data/assist_pipeline.ts | 10 ++ .../config/voice-assistants/assist-pref.ts | 19 +++ ...-config-voice-assistants-assist-devices.ts | 148 ++++++++++++++++++ .../ha-config-voice-assistants.ts | 5 + src/translations/en.json | 9 +- 5 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 src/panels/config/voice-assistants/assist/ha-config-voice-assistants-assist-devices.ts diff --git a/src/data/assist_pipeline.ts b/src/data/assist_pipeline.ts index 3ee5a8a27a0c..e5f60c2d9ccf 100644 --- a/src/data/assist_pipeline.ts +++ b/src/data/assist_pipeline.ts @@ -18,6 +18,11 @@ export interface AssistPipeline { wake_word_id: string | null; } +export interface AssistDevice { + device_id: string; + pipeline_entity: string; +} + export interface AssistPipelineMutableParams { name: string; language: string; @@ -366,3 +371,8 @@ export const fetchAssistPipelineLanguages = (hass: HomeAssistant) => hass.callWS<{ languages: string[] }>({ type: "assist_pipeline/language/list", }); + +export const listAssistDevices = (hass: HomeAssistant) => + hass.callWS({ + type: "assist_pipeline/device/list", + }); diff --git a/src/panels/config/voice-assistants/assist-pref.ts b/src/panels/config/voice-assistants/assist-pref.ts index 7a39414f94a8..fa1350936fb8 100644 --- a/src/panels/config/voice-assistants/assist-pref.ts +++ b/src/panels/config/voice-assistants/assist-pref.ts @@ -12,9 +12,11 @@ import "../../../components/ha-list-item"; import "../../../components/ha-svg-icon"; import "../../../components/ha-switch"; import { + AssistDevice, AssistPipeline, createAssistPipeline, deleteAssistPipeline, + listAssistDevices, listAssistPipelines, setAssistPipelinePreferred, updateAssistPipeline, @@ -39,6 +41,8 @@ export class AssistPref extends LitElement { @state() private _preferred: string | null = null; + @state() private _devices: AssistDevice[] = []; + @property() public cloudStatus?: CloudStatus; protected firstUpdated(changedProps: PropertyValues) { @@ -48,6 +52,9 @@ export class AssistPref extends LitElement { this._pipelines = pipelines.pipelines; this._preferred = pipelines.preferred_pipeline; }); + listAssistDevices(this.hass).then((devices) => { + this._devices = devices; + }); } private _exposedEntitiesCount = memoizeOne( @@ -132,6 +139,18 @@ export class AssistPref extends LitElement { )}
+ ${this._devices?.length + ? html` + + + ${this.hass.localize( + "ui.panel.config.voice_assistants.assistants.pipeline.assist_devices", + { number: this._devices.length } + )} + + + ` + : ""}
`; diff --git a/src/panels/config/voice-assistants/assist/ha-config-voice-assistants-assist-devices.ts b/src/panels/config/voice-assistants/assist/ha-config-voice-assistants-assist-devices.ts new file mode 100644 index 000000000000..86c450f691a3 --- /dev/null +++ b/src/panels/config/voice-assistants/assist/ha-config-voice-assistants-assist-devices.ts @@ -0,0 +1,148 @@ +import { LitElement, PropertyValues, html } from "lit"; +import memoizeOne from "memoize-one"; +import { customElement, property, state } from "lit/decorators"; +import "../../../../layouts/hass-subpage"; +import "../../../../components/data-table/ha-data-table"; +import type { DataTableColumnContainer } from "../../../../components/data-table/ha-data-table"; +import { HomeAssistant } from "../../../../types"; +import { + AssistDevice, + AssistPipeline, + listAssistDevices, + listAssistPipelines, +} from "../../../../data/assist_pipeline"; +import { computeDeviceName } from "../../../../data/device_registry"; +import { navigate } from "../../../../common/navigate"; + +interface AssistDeviceExtra { + pipeline: string | undefined; + last_used: string | undefined; +} + +@customElement("ha-config-voice-assistants-assist-devices") +class AssistDevicesPage extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ type: Boolean }) public narrow!: boolean; + + @state() private _pipelines: Record = {}; + + @state() private _preferred: string | null = null; + + @state() private _devices?: (AssistDevice | AssistDeviceExtra)[]; + + private _columns = memoizeOne( + ( + hass: HomeAssistant, + pipelines: Record, + preferred: string | null + ): DataTableColumnContainer => { + const columns: DataTableColumnContainer = { + name: { + title: hass.localize( + "ui.panel.config.voice_assistants.assistants.pipeline.devices.device" + ), + width: "50%", + filterable: true, + sortable: true, + template: (assistDevice) => + computeDeviceName(hass.devices[assistDevice.device_id], hass), + }, + pipeline: { + title: hass.localize( + "ui.panel.config.voice_assistants.assistants.pipeline.devices.pipeline" + ), + width: "30%", + filterable: true, + sortable: true, + template: (assistDevice) => { + let selected = hass.states[assistDevice.pipeline_entity].state; + if (!pipelines) { + return selected; + } + let isPreferred = false; + + if (selected === "preferred") { + isPreferred = true; + selected = preferred!; + } + + const name = pipelines[selected].name; + + return isPreferred + ? hass.localize("ui.components.pipeline-picker.preferred", { + preferred: name, + }) + : name; + }, + }, + area: { + title: hass.localize( + "ui.panel.config.voice_assistants.assistants.pipeline.devices.area" + ), + width: "20%", + template: (assistDevice) => { + const device = hass.devices[assistDevice.device_id]; + return ( + (device && device.area_id && hass.areas[device.area_id]?.name) || + "" + ); + }, + }, + }; + + return columns; + } + ); + + protected firstUpdated(changedProps: PropertyValues) { + super.firstUpdated(changedProps); + + listAssistPipelines(this.hass).then((pipelines) => { + const lookup: Record = {}; + for (const pipeline of pipelines.pipelines) { + lookup[pipeline.id] = pipeline; + } + + this._pipelines = lookup; + this._preferred = pipelines.preferred_pipeline; + }); + + listAssistDevices(this.hass).then((devices) => { + this._devices = devices; + }); + } + + render() { + return html` + + + + `; + } + + private _handleRowClicked(ev: CustomEvent) { + const device: AssistDevice = ev.detail.id; + navigate(`/config/devices/device/${device}`); + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-config-voice-assistants-assist-devices": AssistDevicesPage; + } +} diff --git a/src/panels/config/voice-assistants/ha-config-voice-assistants.ts b/src/panels/config/voice-assistants/ha-config-voice-assistants.ts index 4c94317ca760..8c99c7808b66 100644 --- a/src/panels/config/voice-assistants/ha-config-voice-assistants.ts +++ b/src/panels/config/voice-assistants/ha-config-voice-assistants.ts @@ -75,6 +75,11 @@ class HaConfigVoiceAssistants extends HassRouterPage { tag: "assist-debug", load: () => import("./debug/assist-debug"), }, + assist: { + tag: "ha-config-voice-assistants-assist-devices", + load: () => + import("./assist/ha-config-voice-assistants-assist-devices"), + }, }, }; diff --git a/src/translations/en.json b/src/translations/en.json index adee4f24b8f4..0ef583607874 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2257,10 +2257,17 @@ "pipeline": { "add_assistant": "Add assistant", "exposed_entities": "[%key:ui::panel::config::cloud::account::google::exposed_entities%]", + "assist_devices": "{number} Assist {number, plural,\n one {device}\n other {devices}\n}", "delete": { "confirm_title": "Delete {name}?", "confirm_text": "{name} will be permanently deleted." }, + "devices": { + "title": "Assist devices", + "device": "Device", + "pipeline": "Assistant", + "area": "Area" + }, "detail": { "update_assistant_action": "Update", "add_assistant_title": "Add assistant", @@ -2269,7 +2276,7 @@ "debug": "Debug", "set_as_preferred": "Set as preferred", "form": { - "name": "Name", + "name": "[%key:ui::common::name%]", "conversation_engine": "Conversation agent", "conversation_language": "[%key:ui::panel::config::voice_assistants::assistants::pipeline::detail::form::language%]", "language": "Language", From b9069b25ade807dab2905c09bc4d355eeef2c03f Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 11 Jan 2024 09:48:10 +0100 Subject: [PATCH 118/361] Assist devices: Move logic from column to data (#19359) * Move logic from column to data * Type --- ...-config-voice-assistants-assist-devices.ts | 111 ++++++++++-------- 1 file changed, 61 insertions(+), 50 deletions(-) diff --git a/src/panels/config/voice-assistants/assist/ha-config-voice-assistants-assist-devices.ts b/src/panels/config/voice-assistants/assist/ha-config-voice-assistants-assist-devices.ts index 86c450f691a3..080ec7843218 100644 --- a/src/panels/config/voice-assistants/assist/ha-config-voice-assistants-assist-devices.ts +++ b/src/panels/config/voice-assistants/assist/ha-config-voice-assistants-assist-devices.ts @@ -1,10 +1,10 @@ import { LitElement, PropertyValues, html } from "lit"; -import memoizeOne from "memoize-one"; import { customElement, property, state } from "lit/decorators"; -import "../../../../layouts/hass-subpage"; +import memoizeOne from "memoize-one"; +import { navigate } from "../../../../common/navigate"; +import { LocalizeFunc } from "../../../../common/translations/localize"; import "../../../../components/data-table/ha-data-table"; import type { DataTableColumnContainer } from "../../../../components/data-table/ha-data-table"; -import { HomeAssistant } from "../../../../types"; import { AssistDevice, AssistPipeline, @@ -12,11 +12,13 @@ import { listAssistPipelines, } from "../../../../data/assist_pipeline"; import { computeDeviceName } from "../../../../data/device_registry"; -import { navigate } from "../../../../common/navigate"; +import "../../../../layouts/hass-subpage"; +import { HomeAssistant } from "../../../../types"; -interface AssistDeviceExtra { - pipeline: string | undefined; - last_used: string | undefined; +interface AssistDeviceExtra extends AssistDevice { + name: string; + pipeline: string; + area: string; } @customElement("ha-config-voice-assistants-assist-devices") @@ -29,65 +31,34 @@ class AssistDevicesPage extends LitElement { @state() private _preferred: string | null = null; - @state() private _devices?: (AssistDevice | AssistDeviceExtra)[]; + @state() private _devices?: AssistDevice[]; private _columns = memoizeOne( - ( - hass: HomeAssistant, - pipelines: Record, - preferred: string | null - ): DataTableColumnContainer => { - const columns: DataTableColumnContainer = { + (localize: LocalizeFunc): DataTableColumnContainer => { + const columns: DataTableColumnContainer = { name: { - title: hass.localize( + title: localize( "ui.panel.config.voice_assistants.assistants.pipeline.devices.device" ), - width: "50%", filterable: true, sortable: true, - template: (assistDevice) => - computeDeviceName(hass.devices[assistDevice.device_id], hass), + grows: true, }, pipeline: { - title: hass.localize( + title: localize( "ui.panel.config.voice_assistants.assistants.pipeline.devices.pipeline" ), width: "30%", filterable: true, sortable: true, - template: (assistDevice) => { - let selected = hass.states[assistDevice.pipeline_entity].state; - if (!pipelines) { - return selected; - } - let isPreferred = false; - - if (selected === "preferred") { - isPreferred = true; - selected = preferred!; - } - - const name = pipelines[selected].name; - - return isPreferred - ? hass.localize("ui.components.pipeline-picker.preferred", { - preferred: name, - }) - : name; - }, }, area: { - title: hass.localize( + title: localize( "ui.panel.config.voice_assistants.assistants.pipeline.devices.area" ), - width: "20%", - template: (assistDevice) => { - const device = hass.devices[assistDevice.device_id]; - return ( - (device && device.area_id && hass.areas[device.area_id]?.name) || - "" - ); - }, + filterable: true, + sortable: true, + width: "30%", }, }; @@ -95,6 +66,38 @@ class AssistDevicesPage extends LitElement { } ); + private _data = memoizeOne( + ( + localize: LocalizeFunc, + deviceReg: HomeAssistant["devices"], + areaReg: HomeAssistant["areas"], + states: HomeAssistant["states"], + pipelines: Record, + preferred: string | null, + assistDevices: AssistDevice[] + ): AssistDeviceExtra[] => + assistDevices.map((assistDevice) => { + const device = deviceReg[assistDevice.device_id]; + const selected = states[assistDevice.pipeline_entity]?.state; + const isPreferred = selected === "preferred"; + const pipeline = isPreferred ? preferred : selected; + const pipelineName = + (pipeline && pipelines[pipeline]?.name) || pipeline; + + return { + ...assistDevice, + name: device ? computeDeviceName(device, this.hass) : "", + pipeline: isPreferred + ? localize("ui.components.pipeline-picker.preferred", { + preferred: pipelineName, + }) + : pipelineName || "", + area: + (device && device.area_id && areaReg[device.area_id]?.name) || "", + }; + }) + ); + protected firstUpdated(changedProps: PropertyValues) { super.firstUpdated(changedProps); @@ -126,8 +129,16 @@ class AssistDevicesPage extends LitElement { clickable id="device_id" .hass=${this.hass} - .columns=${this._columns(this.hass, this._pipelines, this._preferred)} - .data=${this._devices || []} + .columns=${this._columns(this.hass.localize)} + .data=${this._data( + this.hass.localize, + this.hass.devices, + this.hass.areas, + this.hass.states, + this._pipelines, + this._preferred, + this._devices || [] + )} auto-height @row-click=${this._handleRowClicked} > From 03751d2581740e91278fc16ff879adf3d97f8a68 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 11 Jan 2024 09:48:20 +0100 Subject: [PATCH 119/361] =?UTF-8?q?Load=20registries=20in=20core,=20wait?= =?UTF-8?q?=20them=20to=20be=20loaded=20before=20generating=20das=E2=80=A6?= =?UTF-8?q?=20(#19356)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * load registries in core, wait them to be loaded before generating dashboard * import * improve * Split out subscribe functions --- src/data/area_registry.ts | 44 ++---------------------- src/data/device_registry.ts | 41 +++------------------- src/data/entity_registry.ts | 32 ++--------------- src/data/ws-area_registry.ts | 44 ++++++++++++++++++++++++ src/data/ws-device_registry.ts | 37 ++++++++++++++++++++ src/data/ws-entity_registry_display.ts | 35 +++++++++++++++++++ src/entrypoints/core.ts | 14 +++++--- src/panels/lovelace/ha-panel-lovelace.ts | 21 ++++++++--- 8 files changed, 153 insertions(+), 115 deletions(-) create mode 100644 src/data/ws-area_registry.ts create mode 100644 src/data/ws-device_registry.ts create mode 100644 src/data/ws-entity_registry_display.ts diff --git a/src/data/area_registry.ts b/src/data/area_registry.ts index d51f7c528f77..bd0e7c97c35a 100644 --- a/src/data/area_registry.ts +++ b/src/data/area_registry.ts @@ -1,11 +1,10 @@ -import { Connection, createCollection } from "home-assistant-js-websocket"; -import { Store } from "home-assistant-js-websocket/dist/store"; import { stringCompare } from "../common/string/compare"; -import { debounce } from "../common/util/debounce"; import { HomeAssistant } from "../types"; import { DeviceRegistryEntry } from "./device_registry"; import { EntityRegistryEntry } from "./entity_registry"; +export { subscribeAreaRegistry } from "./ws-area_registry"; + export interface AreaRegistryEntry { area_id: string; name: string; @@ -53,45 +52,6 @@ export const deleteAreaRegistryEntry = (hass: HomeAssistant, areaId: string) => area_id: areaId, }); -const fetchAreaRegistry = (conn: Connection) => - conn - .sendMessagePromise({ - type: "config/area_registry/list", - }) - .then((areas) => - (areas as AreaRegistryEntry[]).sort((ent1, ent2) => - stringCompare(ent1.name, ent2.name) - ) - ); - -const subscribeAreaRegistryUpdates = ( - conn: Connection, - store: Store -) => - conn.subscribeEvents( - debounce( - () => - fetchAreaRegistry(conn).then((areas: AreaRegistryEntry[]) => - store.setState(areas, true) - ), - 500, - true - ), - "area_registry_updated" - ); - -export const subscribeAreaRegistry = ( - conn: Connection, - onChange: (areas: AreaRegistryEntry[]) => void -) => - createCollection( - "_areaRegistry", - fetchAreaRegistry, - subscribeAreaRegistryUpdates, - conn, - onChange - ); - export const getAreaEntityLookup = ( entities: EntityRegistryEntry[] ): AreaEntityLookup => { diff --git a/src/data/device_registry.ts b/src/data/device_registry.ts index 4e2d308e0e6c..0127bdf7d383 100644 --- a/src/data/device_registry.ts +++ b/src/data/device_registry.ts @@ -1,8 +1,5 @@ -import { Connection, createCollection } from "home-assistant-js-websocket"; -import type { Store } from "home-assistant-js-websocket/dist/store"; import { computeStateName } from "../common/entity/compute_state_name"; import { caseInsensitiveStringCompare } from "../common/string/compare"; -import { debounce } from "../common/util/debounce"; import type { HomeAssistant } from "../types"; import type { EntityRegistryDisplayEntry, @@ -10,6 +7,11 @@ import type { } from "./entity_registry"; import type { EntitySources } from "./entity_sources"; +export { + fetchDeviceRegistry, + subscribeDeviceRegistry, +} from "./ws-device_registry"; + export interface DeviceRegistryEntry { id: string; config_entries: string[]; @@ -96,39 +98,6 @@ export const removeConfigEntryFromDevice = ( config_entry_id: configEntryId, }); -export const fetchDeviceRegistry = (conn: Connection) => - conn.sendMessagePromise({ - type: "config/device_registry/list", - }); - -const subscribeDeviceRegistryUpdates = ( - conn: Connection, - store: Store -) => - conn.subscribeEvents( - debounce( - () => - fetchDeviceRegistry(conn).then((devices) => - store.setState(devices, true) - ), - 500, - true - ), - "device_registry_updated" - ); - -export const subscribeDeviceRegistry = ( - conn: Connection, - onChange: (devices: DeviceRegistryEntry[]) => void -) => - createCollection( - "_dr", - fetchDeviceRegistry, - subscribeDeviceRegistryUpdates, - conn, - onChange - ); - export const sortDeviceRegistryByName = ( entries: DeviceRegistryEntry[], language: string diff --git a/src/data/entity_registry.ts b/src/data/entity_registry.ts index c55a09aaa33b..61da5aba2a73 100644 --- a/src/data/entity_registry.ts +++ b/src/data/entity_registry.ts @@ -8,6 +8,8 @@ import { HomeAssistant } from "../types"; import { LightColor } from "./light"; import { computeDomain } from "../common/entity/compute_domain"; +export { subscribeEntityRegistryDisplay } from "./ws-entity_registry_display"; + type entityCategory = "config" | "diagnostic"; export interface EntityRegistryDisplayEntry { @@ -22,7 +24,7 @@ export interface EntityRegistryDisplayEntry { display_precision?: number; } -interface EntityRegistryDisplayEntryResponse { +export interface EntityRegistryDisplayEntryResponse { entities: { ei: string; di?: string; @@ -255,34 +257,6 @@ export const subscribeEntityRegistry = ( onChange ); -const subscribeEntityRegistryDisplayUpdates = ( - conn: Connection, - store: Store -) => - conn.subscribeEvents( - debounce( - () => - fetchEntityRegistryDisplay(conn).then((entities) => - store.setState(entities, true) - ), - 500, - true - ), - "entity_registry_updated" - ); - -export const subscribeEntityRegistryDisplay = ( - conn: Connection, - onChange: (entities: EntityRegistryDisplayEntryResponse) => void -) => - createCollection( - "_entityRegistryDisplay", - fetchEntityRegistryDisplay, - subscribeEntityRegistryDisplayUpdates, - conn, - onChange - ); - export const sortEntityRegistryByName = ( entries: EntityRegistryEntry[], language: string diff --git a/src/data/ws-area_registry.ts b/src/data/ws-area_registry.ts new file mode 100644 index 000000000000..0f5c4a38544b --- /dev/null +++ b/src/data/ws-area_registry.ts @@ -0,0 +1,44 @@ +import { Connection, createCollection } from "home-assistant-js-websocket"; +import { Store } from "home-assistant-js-websocket/dist/store"; +import { stringCompare } from "../common/string/compare"; +import { AreaRegistryEntry } from "./area_registry"; +import { debounce } from "../common/util/debounce"; + +const fetchAreaRegistry = (conn: Connection) => + conn + .sendMessagePromise({ + type: "config/area_registry/list", + }) + .then((areas) => + (areas as AreaRegistryEntry[]).sort((ent1, ent2) => + stringCompare(ent1.name, ent2.name) + ) + ); + +const subscribeAreaRegistryUpdates = ( + conn: Connection, + store: Store +) => + conn.subscribeEvents( + debounce( + () => + fetchAreaRegistry(conn).then((areas: AreaRegistryEntry[]) => + store.setState(areas, true) + ), + 500, + true + ), + "area_registry_updated" + ); + +export const subscribeAreaRegistry = ( + conn: Connection, + onChange: (areas: AreaRegistryEntry[]) => void +) => + createCollection( + "_areaRegistry", + fetchAreaRegistry, + subscribeAreaRegistryUpdates, + conn, + onChange + ); diff --git a/src/data/ws-device_registry.ts b/src/data/ws-device_registry.ts new file mode 100644 index 000000000000..85cc26568151 --- /dev/null +++ b/src/data/ws-device_registry.ts @@ -0,0 +1,37 @@ +import { Connection, createCollection } from "home-assistant-js-websocket"; +import { Store } from "home-assistant-js-websocket/dist/store"; +import { DeviceRegistryEntry } from "./device_registry"; +import { debounce } from "../common/util/debounce"; + +export const fetchDeviceRegistry = (conn: Connection) => + conn.sendMessagePromise({ + type: "config/device_registry/list", + }); + +const subscribeDeviceRegistryUpdates = ( + conn: Connection, + store: Store +) => + conn.subscribeEvents( + debounce( + () => + fetchDeviceRegistry(conn).then((devices) => + store.setState(devices, true) + ), + 500, + true + ), + "device_registry_updated" + ); + +export const subscribeDeviceRegistry = ( + conn: Connection, + onChange: (devices: DeviceRegistryEntry[]) => void +) => + createCollection( + "_dr", + fetchDeviceRegistry, + subscribeDeviceRegistryUpdates, + conn, + onChange + ); diff --git a/src/data/ws-entity_registry_display.ts b/src/data/ws-entity_registry_display.ts new file mode 100644 index 000000000000..c57229b6189a --- /dev/null +++ b/src/data/ws-entity_registry_display.ts @@ -0,0 +1,35 @@ +import { Connection, createCollection } from "home-assistant-js-websocket"; +import { Store } from "home-assistant-js-websocket/dist/store"; +import { + EntityRegistryDisplayEntryResponse, + fetchEntityRegistryDisplay, +} from "./entity_registry"; +import { debounce } from "../common/util/debounce"; + +const subscribeEntityRegistryDisplayUpdates = ( + conn: Connection, + store: Store +) => + conn.subscribeEvents( + debounce( + () => + fetchEntityRegistryDisplay(conn).then((entities) => + store.setState(entities, true) + ), + 500, + true + ), + "entity_registry_updated" + ); + +export const subscribeEntityRegistryDisplay = ( + conn: Connection, + onChange: (entities: EntityRegistryDisplayEntryResponse) => void +) => + createCollection( + "_entityRegistryDisplay", + fetchEntityRegistryDisplay, + subscribeEntityRegistryDisplayUpdates, + conn, + onChange + ); diff --git a/src/entrypoints/core.ts b/src/entrypoints/core.ts index 6ca3c2805343..e9bf6b4c001b 100644 --- a/src/entrypoints/core.ts +++ b/src/entrypoints/core.ts @@ -11,19 +11,22 @@ import { import { loadTokens, saveTokens } from "../common/auth/token_storage"; import { hassUrl } from "../data/auth"; import { isExternal } from "../data/external"; -import { getRecorderInfo } from "../data/recorder"; import { subscribeFrontendUserData } from "../data/frontend"; import { fetchConfig } from "../data/lovelace/config/types"; import { fetchResources } from "../data/lovelace/resource"; +import { MAIN_WINDOW_NAME } from "../data/main_window"; +import { WindowWithPreloads } from "../data/preloads"; +import { getRecorderInfo } from "../data/recorder"; +import { subscribeRepairsIssueRegistry } from "../data/repairs"; +import { subscribeAreaRegistry } from "../data/ws-area_registry"; +import { subscribeDeviceRegistry } from "../data/ws-device_registry"; +import { subscribeEntityRegistryDisplay } from "../data/ws-entity_registry_display"; import { subscribePanels } from "../data/ws-panels"; import { subscribeThemes } from "../data/ws-themes"; -import { subscribeRepairsIssueRegistry } from "../data/repairs"; import { subscribeUser } from "../data/ws-user"; import type { ExternalAuth } from "../external_app/external_auth"; import "../resources/array.flat.polyfill"; import "../resources/safari-14-attachshadow-patch"; -import { MAIN_WINDOW_NAME } from "../data/main_window"; -import { WindowWithPreloads } from "../data/preloads"; window.name = MAIN_WINDOW_NAME; (window as any).frontendVersion = __VERSION__; @@ -113,6 +116,9 @@ window.hassConnection.then(({ conn }) => { // do nothing }; subscribeEntities(conn, noop); + subscribeEntityRegistryDisplay(conn, noop); + subscribeDeviceRegistry(conn, noop); + subscribeAreaRegistry(conn, noop); subscribeConfig(conn, noop); subscribeServices(conn, noop); subscribePanels(conn, noop); diff --git a/src/panels/lovelace/ha-panel-lovelace.ts b/src/panels/lovelace/ha-panel-lovelace.ts index eb367df99e19..a767452e3e99 100644 --- a/src/panels/lovelace/ha-panel-lovelace.ts +++ b/src/panels/lovelace/ha-panel-lovelace.ts @@ -1,7 +1,7 @@ import "@material/mwc-button"; import deepFreeze from "deep-freeze"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; -import { html, LitElement, TemplateResult } from "lit"; +import { html, LitElement, PropertyValues, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { constructUrlCurrentPath } from "../../common/url/construct-url"; import { @@ -161,10 +161,15 @@ export class LovelacePanel extends LitElement { `; } - protected firstUpdated(changedProps) { - super.firstUpdated(changedProps); + protected willUpdate(changedProps: PropertyValues) { + super.willUpdate(changedProps); + if (!this.lovelace && this._panelState !== "error") { + this._fetchConfig(false); + } + } - this._fetchConfig(false); + protected firstUpdated(changedProps: PropertyValues): void { + super.firstUpdated(changedProps); if (!this._unsubUpdates) { this._subscribeUpdates(); } @@ -267,6 +272,10 @@ export class LovelacePanel extends LitElement { // If strategy defined, apply it here. if (isStrategyDashboard(rawConf)) { + if (!this.hass?.entities || !this.hass.devices || !this.hass.areas) { + // We need these to generate a dashboard, wait for them + return; + } conf = await generateLovelaceDashboardStrategy( rawConf.strategy, this.hass! @@ -282,6 +291,10 @@ export class LovelacePanel extends LitElement { this._errorMsg = err.message; return; } + if (!this.hass?.entities || !this.hass.devices || !this.hass.areas) { + // We need these to generate a dashboard, wait for them + return; + } conf = await generateLovelaceDashboardStrategy( DEFAULT_CONFIG.strategy, this.hass! From 02a7d0e797a7c354fb7d787283330a5931d798d2 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 11 Jan 2024 11:03:32 +0100 Subject: [PATCH 120/361] Clean up local auth flow, preselect remember me (#19354) --- src/auth/ha-auth-flow.ts | 35 +-- src/auth/ha-authorize.ts | 62 ++--- src/auth/ha-local-auth-flow.ts | 485 --------------------------------- src/data/person.ts | 10 - 4 files changed, 34 insertions(+), 558 deletions(-) delete mode 100644 src/auth/ha-local-auth-flow.ts diff --git a/src/auth/ha-auth-flow.ts b/src/auth/ha-auth-flow.ts index 00070a57b664..fb1d7d7c32f5 100644 --- a/src/auth/ha-auth-flow.ts +++ b/src/auth/ha-auth-flow.ts @@ -21,7 +21,6 @@ import { DataEntryFlowStepForm, } from "../data/data_entry_flow"; import "./ha-auth-form"; -import { fireEvent } from "../common/dom/fire_event"; type State = "loading" | "error" | "step"; @@ -39,7 +38,9 @@ export class HaAuthFlow extends LitElement { @property({ attribute: false }) public step?: DataEntryFlowStep; - @property({ type: Boolean }) private storeToken = false; + @property({ type: Boolean }) private initStoreToken = false; + + @state() private _storeToken = false; @state() private _state: State = "loading"; @@ -56,6 +57,10 @@ export class HaAuthFlow extends LitElement { willUpdate(changedProps: PropertyValues) { super.willUpdate(changedProps); + if (!this.hasUpdated) { + this._storeToken = this.initStoreToken; + } + if (!changedProps.has("step")) { return; } @@ -155,11 +160,6 @@ export class HaAuthFlow extends LitElement { } private _renderForm() { - const showBack = - this.step?.type === "form" && - this.authProvider?.users && - !["select_mfa_module", "mfa"].includes(this.step.step_id); - switch (this._state) { case "step": if (this.step == null) { @@ -168,12 +168,7 @@ export class HaAuthFlow extends LitElement { return html` ${this._renderStep(this.step)} -
- ${showBack - ? html` - ${this.localize("ui.panel.page-authorize.form.previous")} - ` - : nothing} +
${this._computeStepDescription(step)} @@ -269,7 +264,7 @@ export class HaAuthFlow extends LitElement { } private _storeTokenChanged(e: CustomEvent) { - this.storeToken = (e.currentTarget as HTMLInputElement).checked; + this._storeToken = (e.currentTarget as HTMLInputElement).checked; } private async _providerChanged(newProvider?: AuthProvider) { @@ -303,7 +298,7 @@ export class HaAuthFlow extends LitElement { this.redirectUri!, data.result, this.oauth2State, - this.storeToken + this._storeToken ); return; } @@ -385,7 +380,7 @@ export class HaAuthFlow extends LitElement { this.redirectUri!, newStep.result, this.oauth2State, - this.storeToken + this._storeToken ); return; } @@ -400,10 +395,6 @@ export class HaAuthFlow extends LitElement { this._submitting = false; } } - - private _localFlow() { - fireEvent(this, "default-login-flow", { value: false }); - } } declare global { diff --git a/src/auth/ha-authorize.ts b/src/auth/ha-authorize.ts index 97fc3ef4790d..74b1e649d179 100644 --- a/src/auth/ha-authorize.ts +++ b/src/auth/ha-authorize.ts @@ -13,7 +13,6 @@ import { import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin"; import { registerServiceWorker } from "../util/register-service-worker"; import "./ha-auth-flow"; -import "./ha-local-auth-flow"; import("./ha-pick-auth-provider"); @@ -36,12 +35,12 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) { @state() private _authProviders?: AuthProvider[]; + @state() private _preselectStoreToken = false; + @state() private _ownInstance = false; @state() private _error?: string; - @state() private _forceDefaultLogin = false; - constructor() { super(); const query = extractSearchParamsObject() as AuthUrlSearchParams; @@ -84,8 +83,7 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) { display: block; margin-top: 24px; } - ha-auth-flow, - ha-local-auth-flow { + ha-auth-flow { display: flex; justify-content: center; flex-direction: column; @@ -176,44 +174,29 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) { ` : nothing} -
+
${!this._authProvider ? html`

${this.localize("ui.panel.page-authorize.initializing")}

` - : !this._forceDefaultLogin && - this._authProvider!.users && - this.clientId != null && - this.redirectUri != null - ? html`` - : html` - ${inactiveProviders!.length > 0 - ? html` - - ` - : ""}`} + .initStoreToken=${this._preselectStoreToken} + > + ${inactiveProviders!.length > 0 + ? html` + + ` + : ""}`}