From 928b4e6f1edcaf96747b5e0465ba56e46544672e Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Thu, 1 Jun 2023 18:31:18 +0200 Subject: [PATCH 01/29] Add native color picker option (fix for firefox) (#16729) --- .../more-info/components/lights/light-color-picker.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/dialogs/more-info/components/lights/light-color-picker.ts b/src/dialogs/more-info/components/lights/light-color-picker.ts index 20959181b7..720cd2a5bb 100644 --- a/src/dialogs/more-info/components/lights/light-color-picker.ts +++ b/src/dialogs/more-info/components/lights/light-color-picker.ts @@ -603,6 +603,7 @@ class LightColorPicker extends LitElement { input[type="color"] { appearance: none; -webkit-appearance: none; + -moz-appearance: none; border: none; outline: none; display: block; @@ -628,6 +629,10 @@ class LightColorPicker extends LitElement { background: none; } + input[type="color"]::-moz-color-swatch { + display: none; + } + input[type="color"]::-webkit-color-swatch { border: none; } From 27451ca30ebb049747b23f2b95186b43745a0ae6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Jun 2023 22:09:45 -0400 Subject: [PATCH 02/29] Update typescript-eslint monorepo to v5.59.8 (#16730) --- package.json | 4 +-- yarn.lock | 100 +++++++++++++++++++++++++-------------------------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/package.json b/package.json index ba851c2530..ac1ca7a70a 100644 --- a/package.json +++ b/package.json @@ -180,8 +180,8 @@ "@types/sortablejs": "1.15.1", "@types/tar": "6.1.5", "@types/webspeechapi": "0.0.29", - "@typescript-eslint/eslint-plugin": "5.59.7", - "@typescript-eslint/parser": "5.59.7", + "@typescript-eslint/eslint-plugin": "5.59.8", + "@typescript-eslint/parser": "5.59.8", "@web/dev-server": "0.1.38", "@web/dev-server-rollup": "0.4.1", "babel-loader": "9.1.2", diff --git a/yarn.lock b/yarn.lock index 8ef8a1b6c5..836ec615d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4658,14 +4658,14 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/eslint-plugin@npm:5.59.7" +"@typescript-eslint/eslint-plugin@npm:5.59.8": + version: 5.59.8 + resolution: "@typescript-eslint/eslint-plugin@npm:5.59.8" dependencies: "@eslint-community/regexpp": ^4.4.0 - "@typescript-eslint/scope-manager": 5.59.7 - "@typescript-eslint/type-utils": 5.59.7 - "@typescript-eslint/utils": 5.59.7 + "@typescript-eslint/scope-manager": 5.59.8 + "@typescript-eslint/type-utils": 5.59.8 + "@typescript-eslint/utils": 5.59.8 debug: ^4.3.4 grapheme-splitter: ^1.0.4 ignore: ^5.2.0 @@ -4678,43 +4678,43 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10d28bac7a5af9e41767be0bb9c270ee3dcdfeaa38d1b036c6822e7260b88821c460699ba943664eb1ef272d00de6a81b99d7d955332044ea87b624e7ead84a1 + checksum: 3e05cd06149ec3741c3c2fb638e2d19a55687b4614a5c8820433db82997687650297e51c17828d320162ccf4241798cf5712c405561e7605cb17e984a6967f7b languageName: node linkType: hard -"@typescript-eslint/parser@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/parser@npm:5.59.7" +"@typescript-eslint/parser@npm:5.59.8": + version: 5.59.8 + resolution: "@typescript-eslint/parser@npm:5.59.8" dependencies: - "@typescript-eslint/scope-manager": 5.59.7 - "@typescript-eslint/types": 5.59.7 - "@typescript-eslint/typescript-estree": 5.59.7 + "@typescript-eslint/scope-manager": 5.59.8 + "@typescript-eslint/types": 5.59.8 + "@typescript-eslint/typescript-estree": 5.59.8 debug: ^4.3.4 peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: bc44f37a11a44f84ae5f0156213f3e2e49aef2ecac94d9e161a0c721acd29462e288f306ad4648095ac1c0e5a5f62b78280c1735883cf39f79ee3afcba312119 + checksum: bac9f09d8552086ceb882a7b87ce4d98dfaa41579249216c75d97e3fc07af33cddc4cbbd07a127a5823c826a258882643aaf658bec19cb2a434002b55c5f0d12 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/scope-manager@npm:5.59.7" +"@typescript-eslint/scope-manager@npm:5.59.8": + version: 5.59.8 + resolution: "@typescript-eslint/scope-manager@npm:5.59.8" dependencies: - "@typescript-eslint/types": 5.59.7 - "@typescript-eslint/visitor-keys": 5.59.7 - checksum: 43f7ea93fddbe2902122a41050677fe3eff2ea468f435b981592510cfc6136e8c28ac7d3a3e05fb332c0b3078a29bd0c91c35b2b1f4e788b4eb9aaeb70e21583 + "@typescript-eslint/types": 5.59.8 + "@typescript-eslint/visitor-keys": 5.59.8 + checksum: e1e810ee991cfeb433330b04ee949bb6784abe4dbdb7d9480aa7a7536671b4fec914b7803edf662516c8ecb1b31dcff126797f9923270a529c26e2b00b0ea96f languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/type-utils@npm:5.59.7" +"@typescript-eslint/type-utils@npm:5.59.8": + version: 5.59.8 + resolution: "@typescript-eslint/type-utils@npm:5.59.8" dependencies: - "@typescript-eslint/typescript-estree": 5.59.7 - "@typescript-eslint/utils": 5.59.7 + "@typescript-eslint/typescript-estree": 5.59.8 + "@typescript-eslint/utils": 5.59.8 debug: ^4.3.4 tsutils: ^3.21.0 peerDependencies: @@ -4722,23 +4722,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 9cbeffad27b145b478e4cbbab2b44c5b246a9b922f01fd06d401ea4c41a4fa6dc8ba75d13a6409b3b4474ccaf2018770a4c6c599172e22ec2004110e00f4e721 + checksum: d9fde31397da0f0e62a5568f64bad99d06bcd324b7e3aac7fd997a3d045a0fe4c084b2e85d440e0a39645acd2269ad6593f196399c2c0f880d293417fec894e3 languageName: node linkType: hard -"@typescript-eslint/types@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/types@npm:5.59.7" - checksum: 52eccec9e2d631eb2808e48b5dc33a837b5e242fa9eddace89fc707c9f2283b5364f1d38b33d418a08d64f45f6c22f051800898e1881a912f8aac0c3ae300d0a +"@typescript-eslint/types@npm:5.59.8": + version: 5.59.8 + resolution: "@typescript-eslint/types@npm:5.59.8" + checksum: 559473d5601c849eb0da1874a2ac67c753480beed484ad6f6cda62fa6023273f2c3005c7f2864d9c2afb7c6356412d0d304b57db10c53597207f18a7f6cd4f18 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/typescript-estree@npm:5.59.7" +"@typescript-eslint/typescript-estree@npm:5.59.8": + version: 5.59.8 + resolution: "@typescript-eslint/typescript-estree@npm:5.59.8" dependencies: - "@typescript-eslint/types": 5.59.7 - "@typescript-eslint/visitor-keys": 5.59.7 + "@typescript-eslint/types": 5.59.8 + "@typescript-eslint/visitor-keys": 5.59.8 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -4747,35 +4747,35 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: eefe82eedf9ee2e14463c3f2b5b18df084c1328a859b245ee897a9a7075acce7cca0216a21fd7968b75aa64189daa008bfde1e2f9afbcc336f3dfe856e7f342e + checksum: d93371cc866f573a6a1ddc0eb10d498a8e59f36763a99ce21da0737fff2b4c942eef1587216aad273f8d896ebc0b19003677cba63a27d2646aa2c087638963eb languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/utils@npm:5.59.7" +"@typescript-eslint/utils@npm:5.59.8": + version: 5.59.8 + resolution: "@typescript-eslint/utils@npm:5.59.8" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@types/json-schema": ^7.0.9 "@types/semver": ^7.3.12 - "@typescript-eslint/scope-manager": 5.59.7 - "@typescript-eslint/types": 5.59.7 - "@typescript-eslint/typescript-estree": 5.59.7 + "@typescript-eslint/scope-manager": 5.59.8 + "@typescript-eslint/types": 5.59.8 + "@typescript-eslint/typescript-estree": 5.59.8 eslint-scope: ^5.1.1 semver: ^7.3.7 peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: d8682700187ca94cc6441480cb6b87d0514a9748103c15dd93206c5b1c6fefa59063662f27a4103e16abbcfb654a61d479bc55af8f23d96f342431b87f31bb4e + checksum: cbaa057485c7f52c45d0dfb4f5a8e9273abccb1c52dcb4426a79f9e71d2c1062cf2525bad6d4aca5ec42db3fe723d749843bcade5a323bde7fbe4b5d5b5d5c3b languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:5.59.7": - version: 5.59.7 - resolution: "@typescript-eslint/visitor-keys@npm:5.59.7" +"@typescript-eslint/visitor-keys@npm:5.59.8": + version: 5.59.8 + resolution: "@typescript-eslint/visitor-keys@npm:5.59.8" dependencies: - "@typescript-eslint/types": 5.59.7 + "@typescript-eslint/types": 5.59.8 eslint-visitor-keys: ^3.3.0 - checksum: 4367f2ea68dd96a0520485434ad11e1bd26239eeeb3a2150bee7478a0f1df3c2099a39f96486722932be0456bcb7a47a483b452876d1d30bdeb9b81d354eef3d + checksum: 6bfa7918dbb0e08d8a7404aeeef7bcd1a85736dc8d01614d267c0c5ec10f94d2746b50a945bf5c82c54fda67926e8deaeba8565c919da17f725fc11209ef8987 languageName: node linkType: hard @@ -9705,8 +9705,8 @@ __metadata: "@types/sortablejs": 1.15.1 "@types/tar": 6.1.5 "@types/webspeechapi": 0.0.29 - "@typescript-eslint/eslint-plugin": 5.59.7 - "@typescript-eslint/parser": 5.59.7 + "@typescript-eslint/eslint-plugin": 5.59.8 + "@typescript-eslint/parser": 5.59.8 "@vaadin/combo-box": 24.0.7 "@vaadin/vaadin-themable-mixin": 24.0.7 "@vibrant/color": 3.2.1-alpha.1 From b1f5ff26d92b530ff1a56e67c0d5be76b8420db4 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Fri, 2 Jun 2023 02:26:07 -0700 Subject: [PATCH 03/29] Fix device selector when picking devices with no entities (#16734) --- src/components/ha-selector/ha-selector-device.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/ha-selector/ha-selector-device.ts b/src/components/ha-selector/ha-selector-device.ts index 741a8712bd..0af1b288a1 100644 --- a/src/components/ha-selector/ha-selector-device.ts +++ b/src/components/ha-selector/ha-selector-device.ts @@ -77,7 +77,9 @@ export class HaDeviceSelector extends LitElement { .label=${this.label} .helper=${this.helper} .deviceFilter=${this._filterDevices} - .entityFilter=${this._filterEntities} + .entityFilter=${this.selector.device?.entity + ? this._filterEntities + : undefined} .disabled=${this.disabled} .required=${this.required} allow-custom-entity @@ -92,7 +94,9 @@ export class HaDeviceSelector extends LitElement { .value=${this.value} .helper=${this.helper} .deviceFilter=${this._filterDevices} - .entityFilter=${this._filterEntities} + .entityFilter=${this.selector.device?.entity + ? this._filterEntities + : undefined} .disabled=${this.disabled} .required=${this.required} > @@ -115,14 +119,10 @@ export class HaDeviceSelector extends LitElement { ); }; - private _filterEntities = (entity: HassEntity): boolean => { - if (!this.selector.device?.entity) { - return true; - } - return ensureArray(this.selector.device.entity).some((filter) => + private _filterEntities = (entity: HassEntity): boolean => + ensureArray(this.selector.device!.entity).some((filter) => filterSelectorEntities(filter, entity, this._entitySources) ); - }; } declare global { From 0d0e5fdaaac1fa60b447ca87984c97e32147b466 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 2 Jun 2023 12:08:02 +0200 Subject: [PATCH 04/29] Hide ignored entries (#16737) --- .../ha-config-integration-page.ts | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/panels/config/integrations/ha-config-integration-page.ts b/src/panels/config/integrations/ha-config-integration-page.ts index b5ecc21f75..f9a9ad3aea 100644 --- a/src/panels/config/integrations/ha-config-integration-page.ts +++ b/src/panels/config/integrations/ha-config-integration-page.ts @@ -213,6 +213,22 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { ERROR_STATES.includes(entry.state) ); + const normalEntries = configEntries + .filter( + (entry) => + entry.source !== "ignore" && !ERROR_STATES.includes(entry.state) + ) + .sort((a, b) => { + if (Boolean(a.disabled_by) !== Boolean(b.disabled_by)) { + return a.disabled_by ? 1 : -1; + } + return caseInsensitiveStringCompare( + a.title, + b.title, + this.hass.locale.language + ); + }); + return html` - ${configEntries.length === 0 + ${normalEntries.length === 0 ? html`
${this.hass.localize( `ui.panel.config.integrations.integration_page.no_entries` @@ -422,19 +438,7 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {
` : nothing} - ${configEntries - .filter((entry) => !ERROR_STATES.includes(entry.state)) - .sort((a, b) => { - if (Boolean(a.disabled_by) !== Boolean(b.disabled_by)) { - return a.disabled_by ? 1 : -1; - } - return caseInsensitiveStringCompare( - a.title, - b.title, - this.hass.locale.language - ); - }) - .map((item) => this._renderConfigEntry(item))} + ${normalEntries.map((item) => this._renderConfigEntry(item))} From 5667d71b02a2e369ac876bdb7815ccb8a591c936 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 2 Jun 2023 23:40:50 -0400 Subject: [PATCH 05/29] Update dependency @rollup/plugin-node-resolve to v15.1.0 (#16741) 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 ac1ca7a70a..41de542c2c 100644 --- a/package.json +++ b/package.json @@ -162,7 +162,7 @@ "@rollup/plugin-babel": "6.0.3", "@rollup/plugin-commonjs": "25.0.0", "@rollup/plugin-json": "6.0.0", - "@rollup/plugin-node-resolve": "15.0.2", + "@rollup/plugin-node-resolve": "15.1.0", "@rollup/plugin-replace": "5.0.2", "@types/babel__plugin-transform-runtime": "7.9.2", "@types/chromecast-caf-receiver": "6.0.9", diff --git a/yarn.lock b/yarn.lock index 836ec615d0..c30c87085a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3898,9 +3898,9 @@ __metadata: languageName: node linkType: hard -"@rollup/plugin-node-resolve@npm:15.0.2": - version: 15.0.2 - resolution: "@rollup/plugin-node-resolve@npm:15.0.2" +"@rollup/plugin-node-resolve@npm:15.1.0": + version: 15.1.0 + resolution: "@rollup/plugin-node-resolve@npm:15.1.0" dependencies: "@rollup/pluginutils": ^5.0.1 "@types/resolve": 1.20.2 @@ -3913,7 +3913,7 @@ __metadata: peerDependenciesMeta: rollup: optional: true - checksum: 328eafee06ff967a36441b55e77fbd0d4f599d256e5d1977800ee71915846c46bc1b6185df35c7b512ad2b4023b05b65a332be77b8b00b9d8a20f87d056b8166 + checksum: 83617cdbb90cb780251e8b16dc1671e35bde90b8d4d30e008aefe706b5b643057f6299bdd3226b2a30bf5e4f807a880169de3faa47b9f2ba38d39f294f85f951 languageName: node linkType: hard @@ -9686,7 +9686,7 @@ __metadata: "@rollup/plugin-babel": 6.0.3 "@rollup/plugin-commonjs": 25.0.0 "@rollup/plugin-json": 6.0.0 - "@rollup/plugin-node-resolve": 15.0.2 + "@rollup/plugin-node-resolve": 15.1.0 "@rollup/plugin-replace": 5.0.2 "@thomasloven/round-slider": 0.6.0 "@types/babel__plugin-transform-runtime": 7.9.2 From 21f983572cb0a3c155f5384988fdcdc93fcd3c76 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 01:20:24 -0400 Subject: [PATCH 06/29] Update dependency @octokit/plugin-retry to v4.1.4 (#16762) 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 41de542c2c..b050aba13a 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "@babel/preset-typescript": "7.21.5", "@koa/cors": "4.0.0", "@octokit/auth-oauth-device": "4.0.4", - "@octokit/plugin-retry": "4.1.3", + "@octokit/plugin-retry": "4.1.4", "@octokit/rest": "19.0.11", "@open-wc/dev-server-hmr": "0.1.4", "@rollup/plugin-babel": "6.0.3", diff --git a/yarn.lock b/yarn.lock index c30c87085a..0ca93bab9b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3349,15 +3349,15 @@ __metadata: languageName: node linkType: hard -"@octokit/plugin-retry@npm:4.1.3": - version: 4.1.3 - resolution: "@octokit/plugin-retry@npm:4.1.3" +"@octokit/plugin-retry@npm:4.1.4": + version: 4.1.4 + resolution: "@octokit/plugin-retry@npm:4.1.4" dependencies: "@octokit/types": ^9.0.0 bottleneck: ^2.15.3 peerDependencies: "@octokit/core": ">=3" - checksum: f9ed5869be23dddcf1ee896ce996e46a412a586259b55612ba44c82cdeed91436102e6e3ec57db879bd91a4446dcafbaa94632e4e059c6af56d9cca9b163eacb + checksum: 6c81f99c0f4de4e3f55d2a2d4766afb78d7772a7c24e57806ad7f529bc3959073921fcb53322d2b6da946922a830dd3696e20350dc846c9e932574d9bcf5a646 languageName: node linkType: hard @@ -9669,7 +9669,7 @@ __metadata: "@mdi/js": 7.2.96 "@mdi/svg": 7.2.96 "@octokit/auth-oauth-device": 4.0.4 - "@octokit/plugin-retry": 4.1.3 + "@octokit/plugin-retry": 4.1.4 "@octokit/rest": 19.0.11 "@open-wc/dev-server-hmr": 0.1.4 "@polymer/app-layout": 3.1.0 From 9f3e8abe693bde4326cfcb17762cebbeee9a8628 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 5 Jun 2023 09:39:36 +0200 Subject: [PATCH 07/29] Don't show edit favorite colors button if the light doesn't support it (#16750) --- src/data/light.ts | 4 ++++ src/dialogs/more-info/controls/more-info-light.ts | 5 ++++- src/dialogs/more-info/ha-more-info-dialog.ts | 6 +++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/data/light.ts b/src/data/light.ts index 64a9af075f..42a2507731 100644 --- a/src/data/light.ts +++ b/src/data/light.ts @@ -58,6 +58,10 @@ export const lightSupportsBrightness = (entity: LightEntity) => modesSupportingBrightness.includes(mode) ) || false; +export const lightSupportsFavoriteColors = (entity: LightEntity) => + lightSupportsColor(entity) || + lightSupportsColorMode(entity, LightColorMode.COLOR_TEMP); + export const getLightCurrentModeRgbColor = ( entity: LightEntity ): number[] | undefined => diff --git a/src/dialogs/more-info/controls/more-info-light.ts b/src/dialogs/more-info/controls/more-info-light.ts index 1614eaeb3b..f40b41977b 100644 --- a/src/dialogs/more-info/controls/more-info-light.ts +++ b/src/dialogs/more-info/controls/more-info-light.ts @@ -37,6 +37,7 @@ import { lightSupportsBrightness, lightSupportsColor, lightSupportsColorMode, + lightSupportsFavoriteColors, } from "../../../data/light"; import type { HomeAssistant } from "../../../types"; import { moreInfoControlStyle } from "../components/ha-more-info-control-style"; @@ -206,7 +207,9 @@ class MoreInfoLight extends LitElement { ` : nothing} - ${this.entry && (this.editMode || hasFavoriteColors) + ${this.entry && + lightSupportsFavoriteColors(this.stateObj) && + (this.editMode || hasFavoriteColors) ? html` ` : nothing} - ${this._entry && domain === "light" + ${this._entry && + stateObj && + domain === "light" && + lightSupportsFavoriteColors(stateObj) ? html` Date: Mon, 5 Jun 2023 09:39:53 +0200 Subject: [PATCH 08/29] Fix white brightness effect on color wheel (#16738) --- src/components/ha-hs-color-picker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ha-hs-color-picker.ts b/src/components/ha-hs-color-picker.ts index 76bd2a4c6c..ad739818df 100644 --- a/src/components/ha-hs-color-picker.ts +++ b/src/components/ha-hs-color-picker.ts @@ -176,7 +176,7 @@ class HaHsColorPicker extends LitElement { super.updated(changedProps); if ( changedProps.has("colorBrightness") || - changedProps.has("vw") || + changedProps.has("wv") || changedProps.has("ww") || changedProps.has("cw") || changedProps.has("minKelvin") || From 31a3fa02d96d4df2adb694f95c74e52b37e9106d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Mon, 5 Jun 2023 09:46:38 +0200 Subject: [PATCH 09/29] Allow for lazy loading images in markdown (#16746) --- .../documentation/hassio-addon-documentation-tab.ts | 5 ++++- hassio/src/addon-view/info/hassio-addon-info.ts | 1 + src/components/ha-markdown-element.ts | 6 ++++++ src/components/ha-markdown.ts | 4 ++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/hassio/src/addon-view/documentation/hassio-addon-documentation-tab.ts b/hassio/src/addon-view/documentation/hassio-addon-documentation-tab.ts index db64cb1622..98cd11b276 100644 --- a/hassio/src/addon-view/documentation/hassio-addon-documentation-tab.ts +++ b/hassio/src/addon-view/documentation/hassio-addon-documentation-tab.ts @@ -44,7 +44,10 @@ class HassioAddonDocumentationDashboard extends LitElement { : ""}
${this._content - ? html`` + ? html`` : html``}
diff --git a/hassio/src/addon-view/info/hassio-addon-info.ts b/hassio/src/addon-view/info/hassio-addon-info.ts index 356eb64c2b..986090e53f 100644 --- a/hassio/src/addon-view/info/hassio-addon-info.ts +++ b/hassio/src/addon-view/info/hassio-addon-info.ts @@ -659,6 +659,7 @@ class HassioAddonInfo extends LitElement {
diff --git a/src/components/ha-markdown-element.ts b/src/components/ha-markdown-element.ts index 09b29a6ecc..1a4691c917 100644 --- a/src/components/ha-markdown-element.ts +++ b/src/components/ha-markdown-element.ts @@ -11,6 +11,9 @@ class HaMarkdownElement extends ReactiveElement { @property({ type: Boolean }) public breaks = false; + @property({ type: Boolean, attribute: "lazy-images" }) public lazyImages = + false; + protected createRenderRoot() { return this; } @@ -58,6 +61,9 @@ class HaMarkdownElement extends ReactiveElement { // Fire a resize event when images loaded to notify content resized } else if (node instanceof HTMLImageElement) { + if (this.lazyImages) { + node.loading = "lazy"; + } node.addEventListener("load", this._resize); } } diff --git a/src/components/ha-markdown.ts b/src/components/ha-markdown.ts index 795349d256..c248a320e8 100644 --- a/src/components/ha-markdown.ts +++ b/src/components/ha-markdown.ts @@ -15,6 +15,9 @@ export class HaMarkdown extends LitElement { @property({ type: Boolean }) public breaks = false; + @property({ type: Boolean, attribute: "lazy-images" }) public lazyImages = + false; + protected render() { if (!this.content) { return nothing; @@ -24,6 +27,7 @@ export class HaMarkdown extends LitElement { .content=${this.content} .allowSvg=${this.allowSvg} .breaks=${this.breaks} + .lazyImages=${this.lazyImages} >`; } From 3c0afd6cdecb427d6df62da1313e38a5b14a430d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 09:48:45 +0200 Subject: [PATCH 10/29] Update dependency lit to v2.7.5 (#16763) 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 b050aba13a..120ecff610 100644 --- a/package.json +++ b/package.json @@ -118,7 +118,7 @@ "js-yaml": "4.1.0", "leaflet": "1.9.4", "leaflet-draw": "1.0.4", - "lit": "2.7.4", + "lit": "2.7.5", "marked": "4.3.0", "memoize-one": "6.0.0", "node-vibrant": "3.2.1-alpha.1", diff --git a/yarn.lock b/yarn.lock index 0ca93bab9b..10be5bd5b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9765,7 +9765,7 @@ __metadata: leaflet: 1.9.4 leaflet-draw: 1.0.4 lint-staged: 13.2.2 - lit: 2.7.4 + lit: 2.7.5 lit-analyzer: 1.2.1 lodash.template: 4.5.0 magic-string: 0.30.0 @@ -11474,14 +11474,14 @@ __metadata: languageName: node linkType: hard -"lit@npm:2.7.4, lit@npm:^2.0.0, lit@npm:^2.0.0-rc.2, lit@npm:^2.2.1, lit@npm:^2.7.0, lit@npm:^2.7.2, lit@npm:^2.7.4": - version: 2.7.4 - resolution: "lit@npm:2.7.4" +"lit@npm:2.7.5, lit@npm:^2.0.0, lit@npm:^2.0.0-rc.2, lit@npm:^2.2.1, lit@npm:^2.7.0, lit@npm:^2.7.2, lit@npm:^2.7.4": + version: 2.7.5 + resolution: "lit@npm:2.7.5" dependencies: "@lit/reactive-element": ^1.6.0 lit-element: ^3.3.0 lit-html: ^2.7.0 - checksum: 7494f4e814fca0ebf7a73923c85454531aac26ff83f0d4d5afe62ebbc6225363c9df41f88147d79d5d3ab518925ceb9b27a557bee610bbb414ae0339c513f5a3 + checksum: 61a3f87c57136618f47a30b36cdfb592fcba42dcfbdb104d2b5ca291148c2d9a32fcb713bb91090bd08d6897a00e73f8425da6e3626aa080eaf410a32397ae69 languageName: node linkType: hard From 33e15eec227f43d6bdaa30b51750fed92a1b295b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 09:50:00 +0200 Subject: [PATCH 11/29] Update dependency @lit-labs/context to v0.3.2 (#16760) 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 120ecff610..e53f6df7af 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "@fullcalendar/list": "6.1.8", "@fullcalendar/timegrid": "6.1.8", "@lezer/highlight": "1.1.6", - "@lit-labs/context": "0.3.1", + "@lit-labs/context": "0.3.2", "@lit-labs/motion": "1.0.3", "@lit-labs/virtualizer": "2.0.2", "@lrnwebcomponents/simple-tooltip": "7.0.0", diff --git a/yarn.lock b/yarn.lock index 10be5bd5b8..3eb1499e33 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2063,13 +2063,13 @@ __metadata: languageName: node linkType: hard -"@lit-labs/context@npm:0.3.1": - version: 0.3.1 - resolution: "@lit-labs/context@npm:0.3.1" +"@lit-labs/context@npm:0.3.2": + version: 0.3.2 + resolution: "@lit-labs/context@npm:0.3.2" dependencies: "@lit/reactive-element": ^1.5.0 lit: ^2.7.0 - checksum: eca24343bf63a092662a45c0483a77191348514c84aa7fa1a497d45c5741c16e8e61fb294ed8e56d73536b4e7fe96c49beb416417a2c879e670e553e19f5a3f5 + checksum: 55920366798a3337a455c627c0b6911c7b78dee94a783ad77edb9a9e237a2e48201d6cf869f3d0b805316e5c8e8fb817f52f663bc556dd40ca6e8b3168662daf languageName: node linkType: hard @@ -9636,7 +9636,7 @@ __metadata: "@fullcalendar/timegrid": 6.1.8 "@koa/cors": 4.0.0 "@lezer/highlight": 1.1.6 - "@lit-labs/context": 0.3.1 + "@lit-labs/context": 0.3.2 "@lit-labs/motion": 1.0.3 "@lit-labs/virtualizer": 2.0.2 "@lrnwebcomponents/simple-tooltip": 7.0.0 From e6bdc3a15e8794e80b56c72988422099335f52e3 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Mon, 5 Jun 2023 06:27:36 -0400 Subject: [PATCH 12/29] Disable ZHA channel changing when multi-PAN is in use (#16731) * Show baudrate and port in the ZHA network info * Do not allow changing the Zigbee channel with the multiprotocol addon * Include translations as well * Update src/translations/en.json --------- Co-authored-by: Bram Kragten --- src/data/zha.ts | 7 ++++ .../zha/zha-config-dashboard.ts | 34 +++++++++++++++++++ src/translations/en.json | 6 +++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/data/zha.ts b/src/data/zha.ts index c0382b00db..b3f7b084a7 100644 --- a/src/data/zha.ts +++ b/src/data/zha.ts @@ -169,9 +169,16 @@ export interface ZHANetworkBackup { node_info: ZHANetworkBackupNodeInfo; } +export interface ZHADeviceSettings { + path: string; + baudrate?: number; + flow_control?: string; +} + export interface ZHANetworkSettings { settings: ZHANetworkBackup; radio_type: "ezsp" | "znp" | "deconz" | "zigate" | "xbee"; + device: ZHADeviceSettings; } export interface ZHANetworkBackupAndMetadata { diff --git a/src/panels/config/integrations/integration-panels/zha/zha-config-dashboard.ts b/src/panels/config/integrations/integration-panels/zha/zha-config-dashboard.ts index 7176894b84..0518935fca 100644 --- a/src/panels/config/integrations/integration-panels/zha/zha-config-dashboard.ts +++ b/src/panels/config/integrations/integration-panels/zha/zha-config-dashboard.ts @@ -46,6 +46,8 @@ import { } from "../../../../../data/zha"; import { showAlertDialog } from "../../../../../dialogs/generic/show-dialog-box"; +const MULTIPROTOCOL_ADDON_URL = "socket://core-silabs-multiprotocol:9999"; + export const zhaTabs: PageNavigation[] = [ { translationKey: "ui.panel.config.zha.network.caption", @@ -181,6 +183,25 @@ class ZHAConfigDashboard extends LitElement { >${this._networkSettings.radio_type} + + + Serial port + ${this._networkSettings.device.path} + + + ${this._networkSettings.device.baudrate && + !this._networkSettings.device.path.startsWith("socket://") + ? html` + + Baudrate + ${this._networkSettings.device.baudrate} + + ` + : ""} ` : ""}
@@ -255,6 +276,19 @@ class ZHAConfigDashboard extends LitElement { } private async _showChannelMigrationDialog(): Promise { + if (this._networkSettings!.device.path === MULTIPROTOCOL_ADDON_URL) { + showAlertDialog(this, { + title: this.hass.localize( + "ui.panel.config.zha.configuration_page.channel_dialog.title" + ), + text: this.hass.localize( + "ui.panel.config.zha.configuration_page.channel_dialog.text" + ), + warning: true, + }); + return; + } + showZHAChangeChannelDialog(this, { currentChannel: this._networkSettings!.settings.network_info.channel, }); diff --git a/src/translations/en.json b/src/translations/en.json index c8fb2ba4fe..076091255e 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3509,7 +3509,11 @@ "download_backup": "Download Backup", "migrate_radio": "Migrate Radio", "network_settings_title": "Network Settings", - "change_channel": "Change channel" + "change_channel": "Change channel", + "channel_dialog": { + "title": "Multiprotocol addon in use", + "text": "Zigbee and Thread share the same radio and must use the same channel. Change the channel of both networks by reconfiguring multiprotocol from the hardware menu." + } }, "add_device_page": { "spinner": "Searching for Zigbee devices…", From a96eff4d25c68e16878778f9cea33e415222f784 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 5 Jun 2023 13:06:54 +0200 Subject: [PATCH 13/29] Fix padding on thread config panel (#16770) --- .../integration-panels/thread/thread-config-panel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/config/integrations/integration-panels/thread/thread-config-panel.ts b/src/panels/config/integrations/integration-panels/thread/thread-config-panel.ts index c51a84b241..27defda51a 100644 --- a/src/panels/config/integrations/integration-panels/thread/thread-config-panel.ts +++ b/src/panels/config/integrations/integration-panels/thread/thread-config-panel.ts @@ -501,7 +501,7 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) { haStyle, css` .content { - padding: 24px 0 32px; + padding: 24px 8px 32px; max-width: 600px; margin: 0 auto; direction: ltr; From b3370747581327531c029c1981864f4cbd743f32 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 5 Jun 2023 13:48:16 +0200 Subject: [PATCH 14/29] Fix collapsed masonry view in safari (#16772) --- src/panels/lovelace/views/hui-masonry-view.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/panels/lovelace/views/hui-masonry-view.ts b/src/panels/lovelace/views/hui-masonry-view.ts index 60d4154099..20cf91f640 100644 --- a/src/panels/lovelace/views/hui-masonry-view.ts +++ b/src/panels/lovelace/views/hui-masonry-view.ts @@ -320,6 +320,11 @@ export class MasonryView extends LitElement implements LovelaceViewElement { min-width: 0; } + /* Fix for safari */ + .column:has(> *) { + flex-grow: 1; + } + .column:not(:has(> *:not([hidden]))) { flex-grow: 0; } From ddaf403378f3b85670d7a3126be667dcc44628e9 Mon Sep 17 00:00:00 2001 From: Simon Lamon <32477463+silamon@users.noreply.github.com> Date: Mon, 5 Jun 2023 13:57:20 +0200 Subject: [PATCH 15/29] Fix dropdown selection in General Settings (#16754) --- src/onboarding/onboarding-core-config.ts | 10 +++++----- src/panels/config/core/ha-config-section-general.ts | 13 +++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/onboarding/onboarding-core-config.ts b/src/onboarding/onboarding-core-config.ts index eef93d1b54..46621294f4 100644 --- a/src/onboarding/onboarding-core-config.ts +++ b/src/onboarding/onboarding-core-config.ts @@ -128,9 +128,9 @@ class OnboardingCoreConfig extends LitElement {
- ) { + const target = ev.currentTarget as HTMLElement; this[`_${target.getAttribute("name")}`] = ev.detail.value; } - private _handleChange(ev: ValueChangedEvent) { + private _handleChange(ev: Event) { const target = ev.currentTarget as HaTextField; this[`_${target.name}`] = target.value; } diff --git a/src/panels/config/core/ha-config-section-general.ts b/src/panels/config/core/ha-config-section-general.ts index 59899d0984..1d9e3794c0 100644 --- a/src/panels/config/core/ha-config-section-general.ts +++ b/src/panels/config/core/ha-config-section-general.ts @@ -27,7 +27,8 @@ import { ConfigUpdateValues, saveCoreConfig } from "../../../data/core"; import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box"; import "../../../layouts/hass-subpage"; import { haStyle } from "../../../resources/styles"; -import type { HomeAssistant } from "../../../types"; +import type { HomeAssistant, ValueChangedEvent } from "../../../types"; +import type { HaTextField } from "../../../components/ha-textfield"; @customElement("ha-config-section-general") class HaConfigSectionGeneral extends LitElement { @@ -301,13 +302,13 @@ class HaConfigSectionGeneral extends LitElement { this._updateUnits = true; } - private _handleValueChanged(ev) { - const target = ev.currentTarget; - this[`_${target.name}`] = ev.detail.value; + private _handleValueChanged(ev: ValueChangedEvent) { + const target = ev.currentTarget as HTMLElement; + this[`_${target.getAttribute("name")}`] = ev.detail.value; } - private _handleChange(ev) { - const target = ev.currentTarget; + private _handleChange(ev: Event) { + const target = ev.currentTarget as HaTextField; this[`_${target.name}`] = target.value; } From 6c684fd8ee48fbc7c6a782547383b81e079f2ba4 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 5 Jun 2023 14:17:03 +0200 Subject: [PATCH 16/29] Show number config entries when no devices/entities (#16766) --- .../config/integrations/ha-integration-card.ts | 17 +++++++++++++++++ src/translations/en.json | 1 + 2 files changed, 18 insertions(+) diff --git a/src/panels/config/integrations/ha-integration-card.ts b/src/panels/config/integrations/ha-integration-card.ts index 2d4a39b486..28621b5e63 100644 --- a/src/panels/config/integrations/ha-integration-card.ts +++ b/src/panels/config/integrations/ha-integration-card.ts @@ -5,6 +5,7 @@ import { mdiCogOutline, mdiDevices, mdiHandExtendedOutline, + mdiPuzzleOutline, mdiShapeOutline, } from "@mdi/js"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; @@ -140,6 +141,22 @@ export class HaIntegrationCard extends LitElement { ` : ""} + ${devices.length === 0 && entities.length === 0 + ? html` + + + ${this.hass.localize( + `ui.panel.config.integrations.config_entry.entries`, + "count", + this.items.length + )} + + + ` + : ""}
`; } diff --git a/src/translations/en.json b/src/translations/en.json index 076091255e..d8ddbfbbbc 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3266,6 +3266,7 @@ "devices": "{count} {count, plural,\n one {device}\n other {devices}\n}", "entities": "{count} {count, plural,\n one {entity}\n other {entities}\n}", "services": "{count} {count, plural,\n one {service}\n other {services}\n}", + "entries": "{count} {count, plural,\n one {entry}\n other {entries}\n}", "rename": "Rename", "configure": "Configure", "system_options": "System options", From 1bf03f020e2b2523081d4f03580886b51e970c72 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 5 Jun 2023 14:26:51 +0200 Subject: [PATCH 17/29] Fix closing notification drawer (#16769) --- .../notifications/notification-drawer.ts | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/dialogs/notifications/notification-drawer.ts b/src/dialogs/notifications/notification-drawer.ts index ccbb0b2533..5b4eacb27e 100644 --- a/src/dialogs/notifications/notification-drawer.ts +++ b/src/dialogs/notifications/notification-drawer.ts @@ -1,7 +1,7 @@ import "@material/mwc-button"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { LitElement, html, css, nothing } from "lit"; -import { customElement, property, state } from "lit/decorators"; +import { customElement, property, query, state } from "lit/decorators"; import { fireEvent } from "../../common/dom/fire_event"; import { computeDomain } from "../../common/entity/compute_domain"; import "../../components/ha-icon-button-prev"; @@ -13,6 +13,7 @@ import { HomeAssistant } from "../../types"; import "./notification-item"; import "../../components/ha-header-bar"; import "../../components/ha-drawer"; +import type { HaDrawer } from "../../components/ha-drawer"; @customElement("notification-drawer") export class HuiNotificationDrawer extends LitElement { @@ -22,6 +23,8 @@ export class HuiNotificationDrawer extends LitElement { @state() private _open = false; + @query("ha-drawer") private _drawer?: HaDrawer; + private _unsubNotifications?: UnsubscribeFunc; connectedCallback() { @@ -53,12 +56,14 @@ export class HuiNotificationDrawer extends LitElement { } closeDialog = () => { + if (this._drawer) { + this._drawer.open = false; + } if (this._unsubNotifications) { this._unsubNotifications(); this._unsubNotifications = undefined; } this._notifications = []; - this._open = false; fireEvent(this, "dialog-closed", { dialog: this.localName }); }; @@ -87,11 +92,7 @@ export class HuiNotificationDrawer extends LitElement { }); return html` - +
${this.hass.localize("ui.notification_drawer.title")} @@ -99,7 +100,7 @@ export class HuiNotificationDrawer extends LitElement { @@ -132,9 +133,9 @@ export class HuiNotificationDrawer extends LitElement { `; } - private _closeDrawer(ev) { + private _dialogClosed(ev: Event) { ev.stopPropagation(); - this.closeDialog(); + this._open = false; } private _dismissAll() { From 29c564bb69655d455ed64c0450567791e4f255c3 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 5 Jun 2023 15:53:57 +0200 Subject: [PATCH 18/29] Fix maps card with location sources (#16778) --- src/panels/lovelace/cards/hui-map-card.ts | 15 +++++++++++++-- src/panels/lovelace/common/has-changed.ts | 5 ++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/panels/lovelace/cards/hui-map-card.ts b/src/panels/lovelace/cards/hui-map-card.ts index 7f1e2fc200..d84694d048 100644 --- a/src/panels/lovelace/cards/hui-map-card.ts +++ b/src/panels/lovelace/cards/hui-map-card.ts @@ -34,7 +34,10 @@ import { HistoryStates, subscribeHistoryStatesTimeWindow, } from "../../../data/history"; -import { hasConfigOrEntitiesChanged } from "../common/has-changed"; +import { + hasConfigChanged, + hasConfigOrEntitiesChanged, +} from "../common/has-changed"; import { HomeAssistant } from "../../../types"; import { findEntities } from "../common/find-entities"; import { processConfigEntities } from "../common/process-config-entities"; @@ -194,7 +197,15 @@ class HuiMapCard extends LitElement implements LovelaceCard { return true; } - return hasConfigOrEntitiesChanged(this, changedProps); + if (this._config?.geo_location_sources) { + if (oldHass.states !== this.hass.states) { + return true; + } + } + + return this._config?.entities + ? hasConfigOrEntitiesChanged(this, changedProps) + : hasConfigChanged(this, changedProps); } public connectedCallback() { diff --git a/src/panels/lovelace/common/has-changed.ts b/src/panels/lovelace/common/has-changed.ts index 36d2cfabda..1abf9d11ff 100644 --- a/src/panels/lovelace/common/has-changed.ts +++ b/src/panels/lovelace/common/has-changed.ts @@ -4,7 +4,10 @@ import { EntityRegistryDisplayEntry } from "../../../data/entity_registry"; import { HomeAssistant } from "../../../types"; import { processConfigEntities } from "./process-config-entities"; -function hasConfigChanged(element: any, changedProps: PropertyValues): boolean { +export function hasConfigChanged( + element: any, + changedProps: PropertyValues +): boolean { if (changedProps.has("_config")) { return true; } From e044ddcb570f16888f2d6239357d15836fe10871 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 5 Jun 2023 15:55:15 +0200 Subject: [PATCH 19/29] Align+fix date time entity rows (#16774) --- .../components/hui-generic-entity-row.ts | 2 +- .../entity-rows/hui-date-entity-row.ts | 18 ++--- .../entity-rows/hui-datetime-entity-row.ts | 49 ++++++++------ .../hui-input-datetime-entity-row.ts | 65 +++++++++++-------- .../entity-rows/hui-time-entity-row.ts | 12 ++-- 5 files changed, 81 insertions(+), 65 deletions(-) diff --git a/src/panels/lovelace/components/hui-generic-entity-row.ts b/src/panels/lovelace/components/hui-generic-entity-row.ts index 3d1c1e0d0c..347457cb3a 100644 --- a/src/panels/lovelace/components/hui-generic-entity-row.ts +++ b/src/panels/lovelace/components/hui-generic-entity-row.ts @@ -85,7 +85,7 @@ class HuiGenericEntityRow extends LitElement { tabindex=${ifDefined(pointer ? "0" : undefined)} > ${!this.hideName - ? html`
+ @@ -59,9 +57,7 @@ class HuiDateEntityRow extends LitElement implements LovelaceRow { } private _dateChanged(ev: CustomEvent<{ value: string }>): void { - const stateObj = this.hass!.states[this._config!.entity]; - - setDateValue(this.hass!, stateObj.entity_id, ev.detail.value); + setDateValue(this.hass!, this._config!.entity, ev.detail.value); } } diff --git a/src/panels/lovelace/entity-rows/hui-datetime-entity-row.ts b/src/panels/lovelace/entity-rows/hui-datetime-entity-row.ts index bf6b2845e8..e4aecd4cbf 100644 --- a/src/panels/lovelace/entity-rows/hui-datetime-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-datetime-entity-row.ts @@ -18,6 +18,7 @@ import "../components/hui-generic-entity-row"; import { createEntityNotFoundWarning } from "../components/hui-warning"; import type { EntityConfig, LovelaceRow } from "./types"; import "../../../components/ha-time-input"; +import { computeStateName } from "../../../common/entity/compute_state_name"; @customElement("hui-datetime-entity-row") class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow { @@ -51,30 +52,35 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow { `; } - const dateObj = new Date(stateObj.state); - const time = format(dateObj, "HH:mm:ss"); - const date = format(dateObj, "yyyy-MM-dd"); + const unavailable = isUnavailableState(stateObj.state); + + const dateObj = unavailable ? undefined : new Date(stateObj.state); + const time = dateObj ? format(dateObj, "HH:mm:ss") : ""; + const date = dateObj ? format(dateObj, "yyyy-MM-dd") : ""; return html` - - - +
+ + + +
`; } @@ -103,12 +109,17 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow { static get styles(): CSSResultGroup { return css` - ha-date-input + ha-time-input { + ha-time-input { margin-left: 4px; margin-inline-start: 4px; margin-inline-end: initial; direction: var(--direction); } + div { + display: flex; + justify-content: flex-end; + width: 100%; + } `; } } diff --git a/src/panels/lovelace/entity-rows/hui-input-datetime-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-datetime-entity-row.ts index bd595bd4f7..287ea60886 100644 --- a/src/panels/lovelace/entity-rows/hui-input-datetime-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-datetime-entity-row.ts @@ -62,33 +62,39 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow { .hideName=${stateObj.attributes.has_date && stateObj.attributes.has_time} > - ${stateObj.attributes.has_date - ? html` - - - ` - : ``} - ${stateObj.attributes.has_time - ? html` - - ` - : ``} +
+ ${stateObj.attributes.has_date + ? html` + + + ` + : ``} + ${stateObj.attributes.has_time + ? html` + + ` + : ``} +
`; } @@ -126,6 +132,11 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow { margin-inline-end: initial; direction: var(--direction); } + div.both { + display: flex; + justify-content: flex-end; + width: 100%; + } `; } } diff --git a/src/panels/lovelace/entity-rows/hui-time-entity-row.ts b/src/panels/lovelace/entity-rows/hui-time-entity-row.ts index f6fceb3829..66cf5c68b1 100644 --- a/src/panels/lovelace/entity-rows/hui-time-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-time-entity-row.ts @@ -42,16 +42,14 @@ class HuiTimeEntityRow extends LitElement implements LovelaceRow { `; } + const unavailable = isUnavailableState(stateObj.state); + return html` - + From 10ee8fda5b865b230750786a78258ea80cd0d4f8 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 5 Jun 2023 16:08:55 +0200 Subject: [PATCH 20/29] Improve protocol integration add device / integration (#16767) --- .../integrations/protocolIntegrationPicked.ts | 43 +++++++---- .../devices/ha-config-devices-dashboard.ts | 59 ++++++++------- .../config/entities/ha-config-entities.ts | 73 +++++++++++++++---- .../ha-config-integration-page.ts | 9 ++- src/translations/en.json | 3 +- 5 files changed, 125 insertions(+), 62 deletions(-) diff --git a/src/common/integrations/protocolIntegrationPicked.ts b/src/common/integrations/protocolIntegrationPicked.ts index 558bee552d..d6125b172b 100644 --- a/src/common/integrations/protocolIntegrationPicked.ts +++ b/src/common/integrations/protocolIntegrationPicked.ts @@ -17,7 +17,7 @@ export const protocolIntegrationPicked = async ( element: HTMLElement, hass: HomeAssistant, domain: string, - options?: { brand?: string; domain?: string } + options?: { brand?: string; domain?: string; config_entry?: string } ) => { if (options?.domain) { const localize = await hass.loadBackendTranslation("title", options.domain); @@ -32,11 +32,16 @@ export const protocolIntegrationPicked = async ( } if (domain === "zwave_js") { - const entries = await getConfigEntries(hass, { - domain, - }); + const entries = options?.config_entry + ? undefined + : await getConfigEntries(hass, { + domain, + }); - if (!isComponentLoaded(hass, "zwave_js") || !entries.length) { + if ( + !isComponentLoaded(hass, "zwave_js") || + (!options?.config_entry && !entries?.length) + ) { // If the component isn't loaded, ask them to load the integration first showConfirmationDialog(element, { title: hass.localize( @@ -71,14 +76,19 @@ export const protocolIntegrationPicked = async ( } showZWaveJSAddNodeDialog(element, { - entry_id: entries[0].entry_id, + entry_id: options?.config_entry || entries![0].entry_id, }); } else if (domain === "zha") { - const entries = await getConfigEntries(hass, { - domain, - }); + const entries = options?.config_entry + ? undefined + : await getConfigEntries(hass, { + domain, + }); - if (!isComponentLoaded(hass, "zha") || !entries.length) { + if ( + !isComponentLoaded(hass, "zha") || + (!options?.config_entry && !entries?.length) + ) { // If the component isn't loaded, ask them to load the integration first showConfirmationDialog(element, { title: hass.localize( @@ -117,10 +127,15 @@ export const protocolIntegrationPicked = async ( navigate("/config/zha/add"); } else if (domain === "matter") { - const entries = await getConfigEntries(hass, { - domain, - }); - if (!isComponentLoaded(hass, domain) || !entries.length) { + const entries = options?.config_entry + ? undefined + : await getConfigEntries(hass, { + domain, + }); + if ( + !isComponentLoaded(hass, domain) || + (!options?.config_entry && !entries?.length) + ) { // If the component isn't loaded, ask them to load the integration first showConfirmationDialog(element, { title: hass.localize( diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts index bd1402d0e1..0a2a027e30 100644 --- a/src/panels/config/devices/ha-config-devices-dashboard.ts +++ b/src/panels/config/devices/ha-config-devices-dashboard.ts @@ -1,11 +1,15 @@ +import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item"; import { mdiCancel, mdiFilterVariant, mdiPlus } from "@mdi/js"; -import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { HASSDomEvent } from "../../../common/dom/fire_event"; import { computeStateDomain } from "../../../common/entity/compute_state_domain"; +import { + protocolIntegrationPicked, + PROTOCOL_INTEGRATIONS, +} from "../../../common/integrations/protocolIntegrationPicked"; import { navigate } from "../../../common/navigate"; import { blankBeforePercent } from "../../../common/translations/blank_before_percent"; import { LocalizeFunc } from "../../../common/translations/localize"; @@ -39,8 +43,6 @@ import { HomeAssistant, Route } from "../../../types"; import { brandsUrl } from "../../../util/brands-url"; import { configSections } from "../ha-panel-config"; import "../integrations/ha-integration-overflow-menu"; -import { showMatterAddDeviceDialog } from "../integrations/integration-panels/matter/show-dialog-add-matter-device"; -import { showZWaveJSAddNodeDialog } from "../integrations/integration-panels/zwave_js/show-dialog-zwave_js-add-node"; import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog"; interface DeviceRowData extends DeviceRegistryEntry { @@ -186,6 +188,8 @@ export class HaConfigDeviceDashboard extends LitElement { let filterConfigEntry: ConfigEntry | undefined; + const filteredDomains = new Set(); + filters.forEach((value, key) => { if (key === "config_entry") { outputDevices = outputDevices.filter((device) => @@ -193,6 +197,9 @@ export class HaConfigDeviceDashboard extends LitElement { ); startLength = outputDevices.length; filterConfigEntry = entries.find((entry) => entry.entry_id === value); + if (filterConfigEntry) { + filteredDomains.add(filterConfigEntry.domain); + } } if (key === "domain") { const entryIds = entries @@ -202,6 +209,7 @@ export class HaConfigDeviceDashboard extends LitElement { device.config_entries.some((entryId) => entryIds.includes(entryId)) ); startLength = outputDevices.length; + filteredDomains.add(value); } }); @@ -251,6 +259,7 @@ export class HaConfigDeviceDashboard extends LitElement { return { devicesOutput: outputDevices, filteredConfigEntry: filterConfigEntry, + filteredDomains, }; } ); @@ -546,25 +555,25 @@ export class HaConfigDeviceDashboard extends LitElement { } private _addDevice() { - const { filteredConfigEntry } = this._devicesAndFilterDomains( - this.devices, - this.entries, - this.entities, - this.areas, - this._searchParms, - this._showDisabled, - this.hass.localize - ); - if (filteredConfigEntry?.domain === "zha") { - navigate(`/config/zha/add`); - return; - } - if (filteredConfigEntry?.domain === "zwave_js") { - this._showZJSAddDeviceDialog(filteredConfigEntry); - return; - } - if (filteredConfigEntry?.domain === "matter") { - showMatterAddDeviceDialog(this); + const { filteredConfigEntry, filteredDomains } = + this._devicesAndFilterDomains( + this.devices, + this.entries, + this.entities, + this.areas, + this._searchParms, + this._showDisabled, + this.hass.localize + ); + if ( + filteredDomains.size === 1 && + (PROTOCOL_INTEGRATIONS as ReadonlyArray).includes( + [...filteredDomains][0] + ) + ) { + protocolIntegrationPicked(this, this.hass, [...filteredDomains][0], { + config_entry: filteredConfigEntry?.entry_id, + }); return; } showAddIntegrationDialog(this, { @@ -572,12 +581,6 @@ export class HaConfigDeviceDashboard extends LitElement { }); } - private _showZJSAddDeviceDialog(filteredConfigEntry: ConfigEntry) { - showZWaveJSAddNodeDialog(this, { - entry_id: filteredConfigEntry!.entry_id, - }); - } - static get styles(): CSSResultGroup { return [ css` diff --git a/src/panels/config/entities/ha-config-entities.ts b/src/panels/config/entities/ha-config-entities.ts index 2afab3ca2c..fb4673059b 100644 --- a/src/panels/config/entities/ha-config-entities.ts +++ b/src/panels/config/entities/ha-config-entities.ts @@ -67,6 +67,11 @@ import { haStyle } from "../../../resources/styles"; import type { HomeAssistant, Route } from "../../../types"; import { configSections } from "../ha-panel-config"; import "../integrations/ha-integration-overflow-menu"; +import { + protocolIntegrationPicked, + PROTOCOL_INTEGRATIONS, +} from "../../../common/integrations/protocolIntegrationPicked"; +import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog"; export interface StateEntity extends Omit { @@ -348,7 +353,8 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { ? entities.concat(stateEntities) : entities; - const filteredDomains: string[] = []; + let filteredConfigEntry: ConfigEntry | undefined; + const filteredDomains = new Set(); filters.forEach((value, key) => { if (key === "config_entry") { @@ -373,7 +379,8 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { const configEntry = entries.find((entry) => entry.entry_id === value); if (configEntry) { - filteredDomains.push(configEntry.domain); + filteredDomains.add(configEntry.domain); + filteredConfigEntry = configEntry; } } if (key === "domain") { @@ -389,7 +396,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { entity.config_entry_id && entryIds.includes(entity.config_entry_id) ); - filteredDomains.push(value); + filteredDomains.add(value); startLength = filteredEntities.length; } }); @@ -444,7 +451,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { } this._numHiddenEntities = startLength - result.length; - return { filteredEntities: result, filteredDomains: filteredDomains }; + return { filteredEntities: result, filteredConfigEntry, filteredDomains }; } ); @@ -509,7 +516,11 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { this._entries ); - const includeZHAFab = filteredDomains.includes("zha"); + const includeAddDeviceFab = + filteredDomains.size === 1 && + (PROTOCOL_INTEGRATIONS as ReadonlyArray).includes( + [...filteredDomains][0] + ); return html` `} - ${includeZHAFab - ? html` - - - - ` + ${includeAddDeviceFab + ? html` + + ` : nothing} `; @@ -959,6 +970,36 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { this._showHidden = true; } + private _addDevice() { + const { filteredConfigEntry, filteredDomains } = + this._filteredEntitiesAndDomains( + this._entities!, + this._devices, + this._areas, + this._stateEntities, + this._searchParms, + this._showDisabled, + this._showUnavailable, + this._showReadOnly, + this._showHidden, + this._entries + ); + if ( + filteredDomains.size === 1 && + (PROTOCOL_INTEGRATIONS as ReadonlyArray).includes( + [...filteredDomains][0] + ) + ) { + protocolIntegrationPicked(this, this.hass, [...filteredDomains][0], { + config_entry: filteredConfigEntry?.entry_id, + }); + return; + } + showAddIntegrationDialog(this, { + domain: this._searchParms.get("domain") || undefined, + }); + } + static get styles(): CSSResultGroup { return [ haStyle, diff --git a/src/panels/config/integrations/ha-config-integration-page.ts b/src/panels/config/integrations/ha-config-integration-page.ts index f9a9ad3aea..2764832b6f 100644 --- a/src/panels/config/integrations/ha-config-integration-page.ts +++ b/src/panels/config/integrations/ha-config-integration-page.ts @@ -427,13 +427,13 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {

${this.hass.localize( - `ui.panel.config.integrations.integration_page.entries` + "ui.panel.config.integrations.integration_page.entries" )}

${normalEntries.length === 0 ? html`
${this.hass.localize( - `ui.panel.config.integrations.integration_page.no_entries` + "ui.panel.config.integrations.integration_page.no_entries" )}
` : nothing} @@ -446,7 +446,10 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { diff --git a/src/translations/en.json b/src/translations/en.json index d8ddbfbbbc..a0e763a48c 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3252,7 +3252,8 @@ "integration_page": { "entries": "Integration entries", "no_entries": "No entries", - "attention_entries": "Needs attention" + "attention_entries": "Needs attention", + "add": "Add {integration}" }, "config_entry": { "application_credentials": { From 1470eb484fa3eb4aacd2b62ca98b2654eb7dbef2 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 5 Jun 2023 16:10:38 +0200 Subject: [PATCH 21/29] Add more info controls for date/time/datetime (#16775) * Add more info controls for date/time/datetime * Discard changes to src/panels/lovelace/entity-rows/hui-date-entity-row.ts * handle unavailable --- src/dialogs/more-info/const.ts | 3 + .../more-info/controls/more-info-date.ts | 51 ++++++++++++ .../more-info/controls/more-info-datetime.ts | 80 +++++++++++++++++++ .../controls/more-info-input_datetime.ts | 57 ++++++------- .../more-info/controls/more-info-time.ts | 55 +++++++++++++ .../more-info/state_more_info_control.ts | 3 + 6 files changed, 218 insertions(+), 31 deletions(-) create mode 100644 src/dialogs/more-info/controls/more-info-date.ts create mode 100644 src/dialogs/more-info/controls/more-info-datetime.ts create mode 100644 src/dialogs/more-info/controls/more-info-time.ts diff --git a/src/dialogs/more-info/const.ts b/src/dialogs/more-info/const.ts index e9304a55fc..8675c499e1 100644 --- a/src/dialogs/more-info/const.ts +++ b/src/dialogs/more-info/const.ts @@ -34,6 +34,8 @@ export const DOMAINS_WITH_MORE_INFO = [ "configurator", "counter", "cover", + "date", + "datetime", "fan", "group", "humidifier", @@ -49,6 +51,7 @@ export const DOMAINS_WITH_MORE_INFO = [ "siren", "sun", "switch", + "time", "timer", "update", "vacuum", diff --git a/src/dialogs/more-info/controls/more-info-date.ts b/src/dialogs/more-info/controls/more-info-date.ts new file mode 100644 index 0000000000..b53829b557 --- /dev/null +++ b/src/dialogs/more-info/controls/more-info-date.ts @@ -0,0 +1,51 @@ +import { HassEntity } from "home-assistant-js-websocket"; +import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { customElement, property } from "lit/decorators"; +import "../../../components/ha-date-input"; +import "../../../components/ha-time-input"; +import { setDateValue } from "../../../data/date"; +import { isUnavailableState } from "../../../data/entity"; +import type { HomeAssistant } from "../../../types"; + +@customElement("more-info-date") +class MoreInfoDate extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: false }) public stateObj?: HassEntity; + + protected render() { + if (!this.stateObj || isUnavailableState(this.stateObj.state)) { + return nothing; + } + + return html` + + + `; + } + + private _dateChanged(ev: CustomEvent<{ value: string }>): void { + setDateValue(this.hass!, this.stateObj!.entity_id, ev.detail.value); + } + + static get styles(): CSSResultGroup { + return css` + :host { + display: flex; + align-items: center; + justify-content: flex-end; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "more-info-date": MoreInfoDate; + } +} diff --git a/src/dialogs/more-info/controls/more-info-datetime.ts b/src/dialogs/more-info/controls/more-info-datetime.ts new file mode 100644 index 0000000000..b0b25f9bc9 --- /dev/null +++ b/src/dialogs/more-info/controls/more-info-datetime.ts @@ -0,0 +1,80 @@ +import { format } from "date-fns"; +import { HassEntity } from "home-assistant-js-websocket"; +import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { customElement, property } from "lit/decorators"; +import "../../../components/ha-date-input"; +import "../../../components/ha-time-input"; +import { setDateTimeValue } from "../../../data/datetime"; +import { isUnavailableState } from "../../../data/entity"; +import type { HomeAssistant } from "../../../types"; + +@customElement("more-info-datetime") +class MoreInfoDatetime extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: false }) public stateObj?: HassEntity; + + protected render() { + if (!this.stateObj || isUnavailableState(this.stateObj.state)) { + return nothing; + } + + const dateObj = new Date(this.stateObj.state); + const time = format(dateObj, "HH:mm:ss"); + const date = format(dateObj, "yyyy-MM-dd"); + + return html` + + `; + } + + private _stopEventPropagation(ev: Event): void { + ev.stopPropagation(); + } + + private _timeChanged(ev: CustomEvent<{ value: string }>): void { + const dateObj = new Date(this.stateObj!.state); + const newTime = ev.detail.value.split(":").map(Number); + dateObj.setHours(newTime[0], newTime[1], newTime[2]); + + setDateTimeValue(this.hass!, this.stateObj!.entity_id, dateObj); + } + + private _dateChanged(ev: CustomEvent<{ value: string }>): void { + const dateObj = new Date(this.stateObj!.state); + const newDate = ev.detail.value.split("-").map(Number); + dateObj.setFullYear(newDate[0], newDate[1] - 1, newDate[2]); + + setDateTimeValue(this.hass!, this.stateObj!.entity_id, dateObj); + } + + static get styles(): CSSResultGroup { + return css` + :host { + display: flex; + align-items: center; + justify-content: flex-end; + } + ha-date-input + ha-time-input { + margin-left: 4px; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "more-info-datetime": MoreInfoDatetime; + } +} diff --git a/src/dialogs/more-info/controls/more-info-input_datetime.ts b/src/dialogs/more-info/controls/more-info-input_datetime.ts index 4ced398678..68926174d8 100644 --- a/src/dialogs/more-info/controls/more-info-input_datetime.ts +++ b/src/dialogs/more-info/controls/more-info-input_datetime.ts @@ -22,37 +22,32 @@ class MoreInfoInputDatetime extends LitElement { } return html` - ${ - this.stateObj.attributes.has_date - ? html` - - - ` - : `` - } - ${ - this.stateObj.attributes.has_time - ? html` - - ` - : `` - } -
+ ${this.stateObj.attributes.has_date + ? html` + + + ` + : ``} + ${this.stateObj.attributes.has_time + ? html` + + ` + : ``} `; } diff --git a/src/dialogs/more-info/controls/more-info-time.ts b/src/dialogs/more-info/controls/more-info-time.ts new file mode 100644 index 0000000000..c131f7e3de --- /dev/null +++ b/src/dialogs/more-info/controls/more-info-time.ts @@ -0,0 +1,55 @@ +import { HassEntity } from "home-assistant-js-websocket"; +import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { customElement, property } from "lit/decorators"; +import "../../../components/ha-date-input"; +import "../../../components/ha-time-input"; +import { isUnavailableState } from "../../../data/entity"; +import { setTimeValue } from "../../../data/time"; +import type { HomeAssistant } from "../../../types"; + +@customElement("more-info-time") +class MoreInfoTime extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: false }) public stateObj?: HassEntity; + + protected render() { + if (!this.stateObj || isUnavailableState(this.stateObj.state)) { + return nothing; + } + + return html` + + `; + } + + private _stopEventPropagation(ev: Event): void { + ev.stopPropagation(); + } + + private _timeChanged(ev: CustomEvent<{ value: string }>): void { + setTimeValue(this.hass!, this.stateObj!.entity_id, ev.detail.value); + } + + static get styles(): CSSResultGroup { + return css` + :host { + display: flex; + align-items: center; + justify-content: flex-end; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "more-info-time": MoreInfoTime; + } +} diff --git a/src/dialogs/more-info/state_more_info_control.ts b/src/dialogs/more-info/state_more_info_control.ts index 39a7d9f456..7c85f0db71 100644 --- a/src/dialogs/more-info/state_more_info_control.ts +++ b/src/dialogs/more-info/state_more_info_control.ts @@ -13,6 +13,8 @@ const LAZY_LOADED_MORE_INFO_CONTROL = { configurator: () => import("./controls/more-info-configurator"), counter: () => import("./controls/more-info-counter"), cover: () => import("./controls/more-info-cover"), + date: () => import("./controls/more-info-date"), + datetime: () => import("./controls/more-info-datetime"), fan: () => import("./controls/more-info-fan"), group: () => import("./controls/more-info-group"), humidifier: () => import("./controls/more-info-humidifier"), @@ -27,6 +29,7 @@ const LAZY_LOADED_MORE_INFO_CONTROL = { siren: () => import("./controls/more-info-siren"), sun: () => import("./controls/more-info-sun"), switch: () => import("./controls/more-info-switch"), + time: () => import("./controls/more-info-time"), timer: () => import("./controls/more-info-timer"), update: () => import("./controls/more-info-update"), vacuum: () => import("./controls/more-info-vacuum"), From 677cd2de10b0727a0b3f580b408c642313ae564c Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 5 Jun 2023 16:13:27 +0200 Subject: [PATCH 22/29] Fix integration card tooltip (#16779) * Fix integration card tooltip * Update src/panels/config/integrations/ha-integration-header.ts Co-authored-by: Bram Kragten --------- Co-authored-by: Bram Kragten --- .../integrations/ha-integration-header.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/panels/config/integrations/ha-integration-header.ts b/src/panels/config/integrations/ha-integration-header.ts index fbc2217a3c..9aa8db3003 100644 --- a/src/panels/config/integrations/ha-integration-header.ts +++ b/src/panels/config/integrations/ha-integration-header.ts @@ -3,6 +3,7 @@ import { mdiCloud, mdiPackageVariant } from "@mdi/js"; import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; +import { computeRTL } from "../../../common/util/compute_rtl"; import "../../../components/ha-svg-icon"; import { domainToName, IntegrationManifest } from "../../../data/integration"; import { HomeAssistant } from "../../../types"; @@ -94,7 +95,10 @@ export class HaIntegrationHeader extends LitElement { ([icon, description]) => html` - ${description} @@ -184,6 +188,9 @@ export class HaIntegrationHeader extends LitElement { left: 40px; top: 40px; display: flex; + padding: 4px; + inset-inline-start: 40px; + inset-inline-end: initial; } .icons.cloud { background: var(--info-color); @@ -191,14 +198,18 @@ export class HaIntegrationHeader extends LitElement { .icons.double { background: var(--warning-color); left: 28px; + inset-inline-start: 28px; + inset-inline-end: initial; } .icons ha-svg-icon { width: 16px; height: 16px; - margin: 4px; + display: block; } .icons span:not(:first-child) ha-svg-icon { - margin-left: 0; + margin-left: 4px; + margin-inline-start: 4px; + margin-inline-end: inherit; } simple-tooltip { white-space: nowrap; From fe8eb333b97aeb9a08828c05eb4d85814449d551 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 5 Jun 2023 17:23:28 +0200 Subject: [PATCH 23/29] Limit integration card to 1 action row (#16780) --- .../config/integrations/ha-integration-card.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/panels/config/integrations/ha-integration-card.ts b/src/panels/config/integrations/ha-integration-card.ts index 28621b5e63..a0e1aae130 100644 --- a/src/panels/config/integrations/ha-integration-card.ts +++ b/src/panels/config/integrations/ha-integration-card.ts @@ -95,7 +95,9 @@ export class HaIntegrationCard extends LitElement { private _renderSingleEntry(): TemplateResult { const devices = this._getDevices(this.items, this.hass.devices); - const entities = this._getEntities(this.items, this.entityRegistryEntries); + const entities = devices.length + ? [] + : this._getEntities(this.items, this.entityRegistryEntries); const services = !devices.some((device) => device.entry_type !== "service"); @@ -122,8 +124,7 @@ export class HaIntegrationCard extends LitElement { ` - : ""} - ${entities.length > 0 + : entities.length > 0 ? html` @@ -140,9 +141,7 @@ export class HaIntegrationCard extends LitElement { ` - : ""} - ${devices.length === 0 && entities.length === 0 - ? html` + : html` - ` - : ""} + `}
`; } From d5f46a69b00228ff3980f5824db54f2680600512 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 17:45:44 +0200 Subject: [PATCH 24/29] Update dependency @octokit/plugin-retry to v4.1.5 (#16782) 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 e53f6df7af..f246bed9d4 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "@babel/preset-typescript": "7.21.5", "@koa/cors": "4.0.0", "@octokit/auth-oauth-device": "4.0.4", - "@octokit/plugin-retry": "4.1.4", + "@octokit/plugin-retry": "4.1.5", "@octokit/rest": "19.0.11", "@open-wc/dev-server-hmr": "0.1.4", "@rollup/plugin-babel": "6.0.3", diff --git a/yarn.lock b/yarn.lock index 3eb1499e33..31b67fa444 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3349,15 +3349,15 @@ __metadata: languageName: node linkType: hard -"@octokit/plugin-retry@npm:4.1.4": - version: 4.1.4 - resolution: "@octokit/plugin-retry@npm:4.1.4" +"@octokit/plugin-retry@npm:4.1.5": + version: 4.1.5 + resolution: "@octokit/plugin-retry@npm:4.1.5" dependencies: "@octokit/types": ^9.0.0 bottleneck: ^2.15.3 peerDependencies: "@octokit/core": ">=3" - checksum: 6c81f99c0f4de4e3f55d2a2d4766afb78d7772a7c24e57806ad7f529bc3959073921fcb53322d2b6da946922a830dd3696e20350dc846c9e932574d9bcf5a646 + checksum: 37272a0dd2fea5025797bb0f6812899c048468b3ef35c0413154230ef0d5c3e323a76bb9eb971ea5ba498f68407711507336852783443397a185a9a75b28b06c languageName: node linkType: hard @@ -9669,7 +9669,7 @@ __metadata: "@mdi/js": 7.2.96 "@mdi/svg": 7.2.96 "@octokit/auth-oauth-device": 4.0.4 - "@octokit/plugin-retry": 4.1.4 + "@octokit/plugin-retry": 4.1.5 "@octokit/rest": 19.0.11 "@open-wc/dev-server-hmr": 0.1.4 "@polymer/app-layout": 3.1.0 From 45d260f0ce2fb1ce39afb925d1d0eb8ea3612b19 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 5 Jun 2023 17:49:05 +0200 Subject: [PATCH 25/29] Move add config entry button to card (#16783) --- .../ha-config-integration-page.ts | 23 ++++++++----------- src/translations/en.json | 2 +- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/panels/config/integrations/ha-config-integration-page.ts b/src/panels/config/integrations/ha-config-integration-page.ts index 2764832b6f..97bd2204d1 100644 --- a/src/panels/config/integrations/ha-config-integration-page.ts +++ b/src/panels/config/integrations/ha-config-integration-page.ts @@ -15,7 +15,6 @@ import { mdiOpenInNew, mdiPackageVariant, mdiPlayCircleOutline, - mdiPlus, mdiProgressHelper, mdiReload, mdiReloadAlert, @@ -237,7 +236,7 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { >
- +
${normalEntries.map((item) => this._renderConfigEntry(item))} +
+ + ${this.hass.localize( + "ui.panel.config.integrations.integration_page.add_entry" + )} + +
- - - `; } @@ -1182,7 +1177,7 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { display: flex; justify-content: center; } - .card-actions { + .overview .card-actions { padding: 0; } img { diff --git a/src/translations/en.json b/src/translations/en.json index a0e763a48c..3770173a1e 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3253,7 +3253,7 @@ "entries": "Integration entries", "no_entries": "No entries", "attention_entries": "Needs attention", - "add": "Add {integration}" + "add_entry": "Add entry" }, "config_entry": { "application_credentials": { From fcacdf65348718129871ac45dc98f99235e7a9bf Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 5 Jun 2023 17:52:11 +0200 Subject: [PATCH 26/29] Add all devices and entities link to integration page (#16781) --- .../ha-config-integration-page.ts | 176 +++++++++++++----- 1 file changed, 130 insertions(+), 46 deletions(-) diff --git a/src/panels/config/integrations/ha-config-integration-page.ts b/src/panels/config/integrations/ha-config-integration-page.ts index 97bd2204d1..e25ad601fe 100644 --- a/src/panels/config/integrations/ha-config-integration-page.ts +++ b/src/panels/config/integrations/ha-config-integration-page.ts @@ -10,8 +10,10 @@ import { mdiCloud, mdiCog, mdiDelete, + mdiDevices, mdiDotsVertical, mdiDownload, + mdiHandExtendedOutline, mdiOpenInNew, mdiPackageVariant, mdiPlayCircleOutline, @@ -19,6 +21,7 @@ import { mdiReload, mdiReloadAlert, mdiRenameBox, + mdiShapeOutline, mdiStopCircleOutline, } from "@mdi/js"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; @@ -228,6 +231,11 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { ); }); + const devices = this._getDevices(configEntries, this.hass.devices); + const entities = this._getEntities(configEntries, this._entities); + + const services = !devices.some((device) => device.entry_type !== "service"); + return html`
- ${this._logInfo - ? html` 0 + ? html` - ${this._logInfo.level === LogSeverity.DEBUG - ? this.hass.localize( - "ui.panel.config.integrations.config_entry.disable_debug_logging" - ) - : this.hass.localize( - "ui.panel.config.integrations.config_entry.enable_debug_logging" - )} - - ` + + + ${this.hass.localize( + `ui.panel.config.integrations.config_entry.${ + services ? "services" : "devices" + }`, + "count", + devices.length + )} + + + ` + : ""} + ${entities.length > 0 + ? html` + + + ${this.hass.localize( + `ui.panel.config.integrations.config_entry.entities`, + "count", + entities.length + )} + + + ` : ""} ${this._manifest ? html` ` : ""} + ${this._logInfo + ? html` + ${this._logInfo.level === LogSeverity.DEBUG + ? this.hass.localize( + "ui.panel.config.integrations.config_entry.disable_debug_logging" + ) + : this.hass.localize( + "ui.panel.config.integrations.config_entry.enable_debug_logging" + )} + + ` + : ""}
@@ -510,9 +563,9 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { } } - const devices = this._getDevices(item, this.hass.devices); - const services = this._getServices(item, this.hass.devices); - const entities = this._getEntities(item, this._entities); + const devices = this._getConfigEntryDevices(item); + const services = this._getConfigEntryServices(item); + const entities = this._getConfigEntryEntities(item); let devicesLine: (TemplateResult | string)[] = []; @@ -809,49 +862,77 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { private _getEntities = memoizeOne( ( - configEntry: ConfigEntry, + configEntry: ConfigEntry[], entityRegistryEntries: EntityRegistryEntry[] ): EntityRegistryEntry[] => { if (!entityRegistryEntries) { return []; } + const entryIds = configEntry.map((entry) => entry.entry_id); return entityRegistryEntries.filter( - (entity) => entity.config_entry_id === configEntry.entry_id + (entity) => + entity.config_entry_id && entryIds.includes(entity.config_entry_id) ); } ); private _getDevices = memoizeOne( ( - configEntry: ConfigEntry, + configEntry: ConfigEntry[], deviceRegistryEntries: HomeAssistant["devices"] ): DeviceRegistryEntry[] => { if (!deviceRegistryEntries) { return []; } - return Object.values(deviceRegistryEntries).filter( - (device) => - device.config_entries.includes(configEntry.entry_id) && - device.entry_type !== "service" + const entryIds = configEntry.map((entry) => entry.entry_id); + return Object.values(deviceRegistryEntries).filter((device) => + device.config_entries.some((entryId) => entryIds.includes(entryId)) ); } ); - private _getServices = memoizeOne( - ( - configEntry: ConfigEntry, - deviceRegistryEntries: HomeAssistant["devices"] - ): DeviceRegistryEntry[] => { - if (!deviceRegistryEntries) { - return []; - } - return Object.values(deviceRegistryEntries).filter( - (device) => - device.config_entries.includes(configEntry.entry_id) && - device.entry_type === "service" - ); - } - ); + private _getConfigEntryEntities = ( + configEntry: ConfigEntry + ): EntityRegistryEntry[] => { + const entries = this._domainConfigEntries( + this.domain, + this._extraConfigEntries || this.configEntries + ); + const entityRegistryEntries = this._getEntities(entries, this._entities); + return entityRegistryEntries.filter( + (entity) => entity.config_entry_id === configEntry.entry_id + ); + }; + + private _getConfigEntryDevices = ( + configEntry: ConfigEntry + ): DeviceRegistryEntry[] => { + const entries = this._domainConfigEntries( + this.domain, + this._extraConfigEntries || this.configEntries + ); + const deviceRegistryEntries = this._getDevices(entries, this.hass.devices); + return Object.values(deviceRegistryEntries).filter( + (device) => + device.config_entries.includes(configEntry.entry_id) && + device.entry_type !== "service" + ); + }; + + private _getConfigEntryServices = ( + configEntry: ConfigEntry + ): DeviceRegistryEntry[] => { + const entries = this._domainConfigEntries( + this.domain, + this._extraConfigEntries || this.configEntries + ); + const deviceRegistryEntries = this._getDevices(entries, this.hass.devices); + return Object.values(deviceRegistryEntries).filter( + (device) => + device.config_entries.includes(configEntry.entry_id) && + device.entry_type === "service" + ); + }; private _showOptions(ev) { showOptionsFlowDialog( @@ -1223,6 +1304,9 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { .attention { primary-color: var(--error-color); } + .warning { + color: var(--warning-color); + } .state-error { --state-message-color: var(--error-color); --text-on-state-color: var(--text-primary-color); From b8efc06caa87c62b7ccb7eaee4125cf3b46c0fcd Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 5 Jun 2023 18:22:38 +0200 Subject: [PATCH 27/29] Bumped version to 20230605.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8a0190bd63..bfaaa029d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20230601.1" +version = "20230605.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From 47fdae764f2bd563e2943384099e54e049f79a5d Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 5 Jun 2023 19:00:06 +0200 Subject: [PATCH 28/29] Improve display of disabled config entries (#16784) --- .../ha-config-integration-page.ts | 200 ++++++++++++------ 1 file changed, 133 insertions(+), 67 deletions(-) diff --git a/src/panels/config/integrations/ha-config-integration-page.ts b/src/panels/config/integrations/ha-config-integration-page.ts index e25ad601fe..58801d08fe 100644 --- a/src/panels/config/integrations/ha-config-integration-page.ts +++ b/src/panels/config/integrations/ha-config-integration-page.ts @@ -519,21 +519,7 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { let stateTextExtra: TemplateResult | string | undefined; let icon: string = mdiAlertCircle; - if (item.disabled_by) { - stateText = [ - "ui.panel.config.integrations.config_entry.disable.disabled_cause", - "cause", - this.hass.localize( - `ui.panel.config.integrations.config_entry.disable.disabled_by.${item.disabled_by}` - ) || item.disabled_by, - ]; - if (item.state === "failed_unload") { - stateTextExtra = html`. - ${this.hass.localize( - "ui.panel.config.integrations.config_entry.disable_restart_confirm" - )}.`; - } - } else if (item.state === "not_loaded") { + if (!item.disabled_by && item.state === "not_loaded") { stateText = ["ui.panel.config.integrations.config_entry.not_loaded"]; } else if (item.state === "setup_in_progress") { icon = mdiProgressHelper; @@ -569,60 +555,81 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { let devicesLine: (TemplateResult | string)[] = []; - for (const [items, localizeKey] of [ - [devices, "devices"], - [services, "services"], - ] as const) { - if (items.length === 0) { - continue; + if (item.disabled_by) { + devicesLine.push( + this.hass.localize( + "ui.panel.config.integrations.config_entry.disable.disabled_cause", + { + cause: + this.hass.localize( + `ui.panel.config.integrations.config_entry.disable.disabled_by.${item.disabled_by}` + ) || item.disabled_by, + } + ) + ); + if (item.state === "failed_unload") { + devicesLine.push(`. + ${this.hass.localize( + "ui.panel.config.integrations.config_entry.disable_restart_confirm" + )}.`); + } + } else { + for (const [items, localizeKey] of [ + [devices, "devices"], + [services, "services"], + ] as const) { + if (items.length === 0) { + continue; + } + const url = + items.length === 1 + ? `/config/devices/device/${items[0].id}` + : `/config/devices/dashboard?historyBack=1&config_entry=${item.entry_id}`; + devicesLine.push( + // no white space before/after template on purpose + html`${this.hass.localize( + `ui.panel.config.integrations.config_entry.${localizeKey}`, + "count", + items.length + )}` + ); + } + + if (entities.length) { + devicesLine.push( + // no white space before/after template on purpose + html`${this.hass.localize( + "ui.panel.config.integrations.config_entry.entities", + "count", + entities.length + )}` + ); + } + + if (devicesLine.length === 0) { + devicesLine = ["No devices or entities"]; + } else if (devicesLine.length === 2) { + devicesLine = [ + devicesLine[0], + ` ${this.hass.localize("ui.common.and")} `, + devicesLine[1], + ]; + } else if (devicesLine.length === 3) { + devicesLine = [ + devicesLine[0], + ", ", + devicesLine[1], + ` ${this.hass.localize("ui.common.and")} `, + devicesLine[2], + ]; } - const url = - items.length === 1 - ? `/config/devices/device/${items[0].id}` - : `/config/devices/dashboard?historyBack=1&config_entry=${item.entry_id}`; - devicesLine.push( - // no white space before/after template on purpose - html`${this.hass.localize( - `ui.panel.config.integrations.config_entry.${localizeKey}`, - "count", - items.length - )}` - ); } - if (entities.length) { - devicesLine.push( - // no white space before/after template on purpose - html`${this.hass.localize( - "ui.panel.config.integrations.config_entry.entities", - "count", - entities.length - )}` - ); - } - - if (devicesLine.length === 0) { - devicesLine = ["No devices or entities"]; - } else if (devicesLine.length === 2) { - devicesLine = [ - devicesLine[0], - ` ${this.hass.localize("ui.common.and")} `, - devicesLine[1], - ]; - } else if (devicesLine.length === 3) { - devicesLine = [ - devicesLine[0], - ", ", - devicesLine[1], - ` ${this.hass.localize("ui.common.and")} `, - devicesLine[2], - ]; - } return html`` : ""} + ${item.disabled_by && devices.length + ? html` + + + ${this.hass.localize( + `ui.panel.config.integrations.config_entry.devices`, + "count", + devices.length + )} + + + ` + : ""} + ${item.disabled_by && services.length + ? html` + + + ${this.hass.localize( + `ui.panel.config.integrations.config_entry.services`, + "count", + services.length + )} + + + ` + : ""} + ${item.disabled_by && entities.length + ? html` + + + ${this.hass.localize( + `ui.panel.config.integrations.config_entry.entities`, + "count", + entities.length + )} + + + ` + : ""} ${!item.disabled_by && RECOVERABLE_STATES.includes(item.state) && item.supports_unload && @@ -1282,6 +1345,9 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { --mdc-list-item-meta-size: auto; --mdc-list-item-meta-display: flex; } + ha-button-menu ha-list-item { + --mdc-list-item-meta-size: 24px; + } ha-list-item.config_entry::after { position: absolute; top: 0; @@ -1305,7 +1371,7 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { primary-color: var(--error-color); } .warning { - color: var(--warning-color); + color: var(--error-color); } .state-error { --state-message-color: var(--error-color); From 93e31df106b6d114c4a57ec64a92a099421552e2 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 5 Jun 2023 19:18:42 +0200 Subject: [PATCH 29/29] Use integration_type as header for config entries (#16786) --- .../ha-config-integration-page.ts | 20 +++++++++++++------ src/translations/en.json | 12 ++++++++++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/panels/config/integrations/ha-config-integration-page.ts b/src/panels/config/integrations/ha-config-integration-page.ts index 58801d08fe..1f1e13b0cd 100644 --- a/src/panels/config/integrations/ha-config-integration-page.ts +++ b/src/panels/config/integrations/ha-config-integration-page.ts @@ -478,9 +478,13 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {

- ${this.hass.localize( - "ui.panel.config.integrations.integration_page.entries" - )} + ${this._manifest?.integration_type + ? this.hass.localize( + `ui.panel.config.integrations.integration_page.entries_${this._manifest?.integration_type}` + ) + : this.hass.localize( + `ui.panel.config.integrations.integration_page.entries` + )}

${normalEntries.length === 0 ? html`
@@ -494,9 +498,13 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {
- ${this.hass.localize( - "ui.panel.config.integrations.integration_page.add_entry" - )} + ${this._manifest?.integration_type + ? this.hass.localize( + `ui.panel.config.integrations.integration_page.add_${this._manifest?.integration_type}` + ) + : this.hass.localize( + `ui.panel.config.integrations.integration_page.add_entry` + )}
diff --git a/src/translations/en.json b/src/translations/en.json index 3770173a1e..2f11673fe8 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3251,9 +3251,19 @@ }, "integration_page": { "entries": "Integration entries", + "entries_device": "Devices", + "entries_hub": "Hubs", + "entries_service": "Services", + "entries_helper": "Helpers", + "entries_hardware": "Hardware", "no_entries": "No entries", "attention_entries": "Needs attention", - "add_entry": "Add entry" + "add_entry": "Add entry", + "add_device": "Add device", + "add_hub": "Add hub", + "add_service": "Add service", + "add_helper": "Add helper", + "add_hardware": "Add hardware" }, "config_entry": { "application_credentials": {