From 0c3fd8f3ad226fbc440d68ca6b450ed637324eb3 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 10 Dec 2021 14:41:09 +0100 Subject: [PATCH 01/11] typo login -> log in (#10850) --- 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 f4ac593a0c..d9e79df1f9 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2515,7 +2515,7 @@ "admin": "Administrator", "group": "Group", "active": "Active", - "local_only": "Can only login from the local network", + "local_only": "Can only log in from the local network", "system_generated": "System generated", "system_generated_users_not_removable": "Unable to remove system generated users.", "system_generated_users_not_editable": "Unable to update system generated users.", From cea40610c097dbd0b54c2944e5dab29833a750d3 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 10 Dec 2021 14:44:40 +0100 Subject: [PATCH 02/11] Add base trigger to struct (#10851) --- src/panels/config/automation/structs.ts | 7 ++++- .../types/ha-automation-trigger-state.ts | 31 +++++++++++++------ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/panels/config/automation/structs.ts b/src/panels/config/automation/structs.ts index eb6baefa97..d54d9761f4 100644 --- a/src/panels/config/automation/structs.ts +++ b/src/panels/config/automation/structs.ts @@ -1,4 +1,9 @@ -import { object, optional, number } from "superstruct"; +import { object, optional, number, string } from "superstruct"; + +export const baseTriggerStruct = object({ + platform: string(), + id: optional(string()), +}); export const forDictStruct = object({ days: optional(number()), diff --git a/src/panels/config/automation/trigger/types/ha-automation-trigger-state.ts b/src/panels/config/automation/trigger/types/ha-automation-trigger-state.ts index e75f2f8b33..9e362634ea 100644 --- a/src/panels/config/automation/trigger/types/ha-automation-trigger-state.ts +++ b/src/panels/config/automation/trigger/types/ha-automation-trigger-state.ts @@ -1,7 +1,15 @@ import "@polymer/paper-input/paper-input"; import { html, LitElement, PropertyValues } from "lit"; import { customElement, property } from "lit/decorators"; -import { assert, literal, object, optional, string, union } from "superstruct"; +import { + assert, + assign, + literal, + object, + optional, + string, + union, +} from "superstruct"; import { createDurationData } from "../../../../../common/datetime/create_duration_data"; import { fireEvent } from "../../../../../common/dom/fire_event"; import { hasTemplate } from "../../../../../common/string/has-template"; @@ -10,20 +18,23 @@ import "../../../../../components/entity/ha-entity-picker"; import "../../../../../components/ha-duration-input"; import { StateTrigger } from "../../../../../data/automation"; import { HomeAssistant } from "../../../../../types"; -import { forDictStruct } from "../../structs"; +import { baseTriggerStruct, forDictStruct } from "../../structs"; import { handleChangeEvent, TriggerElement, } from "../ha-automation-trigger-row"; -const stateTriggerStruct = object({ - platform: literal("state"), - entity_id: string(), - attribute: optional(string()), - from: optional(string()), - to: optional(string()), - for: optional(union([string(), forDictStruct])), -}); +const stateTriggerStruct = assign( + baseTriggerStruct, + object({ + platform: literal("state"), + entity_id: string(), + attribute: optional(string()), + from: optional(string()), + to: optional(string()), + for: optional(union([string(), forDictStruct])), + }) +); @customElement("ha-automation-trigger-state") export class HaStateTrigger extends LitElement implements TriggerElement { From 48c66e63497cea6c2817c569f8c31815ab87421b Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Fri, 10 Dec 2021 18:49:53 +0100 Subject: [PATCH 03/11] Tweak some energy related translation strings (#10852) --- src/translations/en.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/translations/en.json b/src/translations/en.json index d9e79df1f9..d6e784beb4 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -1146,7 +1146,7 @@ "cost_number": "Use a static price", "cost_number_input": "Price per {unit}", "gas_usage": "Gas usage", - "m3_or_kWh": "m³ or kWh" + "m3_or_kWh": "ft³, m³, Wh, kWh or MWh" } }, "device_consumption": { @@ -1187,19 +1187,19 @@ }, "entity_unexpected_unit_energy": { "title": "Unexpected unit of measurement", - "description": "The following entities do not have the expected units of measurement 'kWh' or 'Wh':" + "description": "The following entities do not have the expected units of measurement 'Wh', 'kWh' or 'MWh':" }, "entity_unexpected_unit_gas": { "title": "Unexpected unit of measurement", - "description": "The following entities do not have the expected units of measurement 'kWh', 'm³' or 'ft³':" + "description": "The following entities do not have the expected units of measurement 'Wh', 'kWh' or 'MWh' for an energy sensor or 'm³' or 'ft³' for a gas sensor:" }, "entity_unexpected_unit_energy_price": { "title": "Unexpected unit of measurement", - "description": "The following entities do not have the expected units of measurement ''{currency}/kWh'' or ''{currency}/Wh'':" + "description": "The following entities do not have the expected units of measurement ''{currency}/kWh'', ''{currency}/Wh'' or ''{currency}/MWh'':" }, "entity_unexpected_unit_gas_price": { "title": "Unexpected unit of measurement", - "description": "The following entities do not have the expected units of measurement ''{currency}/kWh'', ''{currency}/Wh'', ''{currency}/m³'' or ''{currency}/ft³'':" + "description": "The following entities do not have the expected units of measurement ''{currency}/kWh'', ''{currency}/Wh'', ''{currency}/MWh'', ''{currency}/m³'' or ''{currency}/ft³'':" }, "entity_unexpected_state_class": { "title": "Unexpected state class", From bec5c564b62b63199dea33776127037f1d149768 Mon Sep 17 00:00:00 2001 From: Matthias de Baat Date: Fri, 10 Dec 2021 20:18:05 +0100 Subject: [PATCH 04/11] Update blueprint description (#10854) --- 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 d6e784beb4..96ebbaa632 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -939,7 +939,7 @@ }, "blueprints": { "title": "Blueprints", - "description": "Manage blueprints" + "description": "Pre-made automations and scripts by the community" }, "supervisor": { "title": "Add-ons, Backups & Supervisor", From 585648ac4cd13b901d2a7e616c7ff6c3117dc5fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Sat, 11 Dec 2021 08:30:35 +0100 Subject: [PATCH 05/11] Revert "handle ha-radio and ha-checkbox in ha-formfield" (#10863) --- src/components/ha-formfield.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/components/ha-formfield.ts b/src/components/ha-formfield.ts index 8a1e60e480..e0452e0db7 100644 --- a/src/components/ha-formfield.ts +++ b/src/components/ha-formfield.ts @@ -5,22 +5,6 @@ import { customElement } from "lit/decorators"; @customElement("ha-formfield") // @ts-expect-error export class HaFormfield extends Formfield { - protected _labelClick() { - const input = this.input; - if (input) { - input.focus(); - switch (input.tagName) { - case "HA-CHECKBOX": - case "HA-RADIO": - (input as any).checked = !(input as any).checked; - break; - default: - input.click(); - break; - } - } - } - protected static get styles(): CSSResultGroup { return [ Formfield.styles, From ca6fd6c77040e378b8ec7823df7ccd8d279c6ebf Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Sat, 11 Dec 2021 17:01:24 +0100 Subject: [PATCH 06/11] Prevent quickbar command entry duplicates (#10861) --- src/dialogs/quick-bar/ha-quick-bar.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index 80afe58dd7..3394c575a2 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -99,6 +99,8 @@ export class QuickBar extends LitElement { private _focusSet = false; + private _focusListElement?: ListItem | null; + public async showDialog(params: QuickBarParams) { this._commandMode = params.commandMode || this._toggleIfAlreadyOpened(); this._initializeItemsIfNeeded(); @@ -317,7 +319,8 @@ export class QuickBar extends LitElement { } else if (ev.code === "ArrowDown") { ev.preventDefault(); this._getItemAtIndex(0)?.focus(); - this._getItemAtIndex(1)?.focus(); + this._focusSet = true; + this._focusListElement = this._getItemAtIndex(0); } } @@ -350,6 +353,11 @@ export class QuickBar extends LitElement { this._initializeItemsIfNeeded(); this._filter = this._search; } else { + if (this._focusSet && this._focusListElement) { + this._focusSet = false; + // @ts-ignore + this._focusListElement.rippleHandlers.endFocus(); + } this._debouncedSetFilter(this._search); } } @@ -366,12 +374,14 @@ export class QuickBar extends LitElement { private _setFocusFirstListItem() { // @ts-ignore this._getItemAtIndex(0)?.rippleHandlers.startFocus(); + this._focusListElement = this._getItemAtIndex(0); } private _handleListItemKeyDown(ev: KeyboardEvent) { const isSingleCharacter = ev.key.length === 1; const isFirstListItem = (ev.target as HTMLElement).getAttribute("index") === "0"; + this._focusListElement = ev.target as ListItem; if (ev.key === "ArrowUp") { if (isFirstListItem) { this._filterInputField?.focus(); @@ -511,7 +521,13 @@ export class QuickBar extends LitElement { if (page.component) { const info = this._getNavigationInfoFromConfig(page); - if (info) { + // Add to list, but only if we do not already have an entry for the same path and component + if ( + info && + !items.some( + (e) => e.path === info.path && e.component === info.component + ) + ) { items.push(info); } } From bfb84a834fc87cc3b092e4c37d1a8bd07f8e3ea7 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Sat, 11 Dec 2021 17:12:41 +0100 Subject: [PATCH 07/11] Still have manual input if camera is not supported (#10849) * Still have manual input if camera is not supported * Adjust & fix --- src/components/ha-qr-scanner.ts | 53 ++++++++++++++++--- .../zwave_js/dialog-zwave_js-add-node.ts | 12 +++-- src/translations/en.json | 10 +++- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/components/ha-qr-scanner.ts b/src/components/ha-qr-scanner.ts index 7ef687cafe..4b4c3d859c 100644 --- a/src/components/ha-qr-scanner.ts +++ b/src/components/ha-qr-scanner.ts @@ -1,5 +1,7 @@ import "@material/mwc-list/mwc-list-item"; import "@material/mwc-select/mwc-select"; +import "@material/mwc-textfield/mwc-textfield"; +import type { TextField } from "@material/mwc-textfield/mwc-textfield"; import { mdiCamera } from "@mdi/js"; import { css, html, LitElement, PropertyValues, TemplateResult } from "lit"; import { customElement, property, query, state } from "lit/decorators"; @@ -9,6 +11,7 @@ import { stopPropagation } from "../common/dom/stop_propagation"; import { LocalizeFunc } from "../common/translations/localize"; import "./ha-alert"; import "./ha-button-menu"; +import "@material/mwc-button/mwc-button"; @customElement("ha-qr-scanner") class HaQrScanner extends LitElement { @@ -26,6 +29,8 @@ class HaQrScanner extends LitElement { @query("#canvas-container", true) private _canvasContainer!: HTMLDivElement; + @query("mwc-textfield") private _manualInput?: TextField; + public disconnectedCallback(): void { super.disconnectedCallback(); this._qrNotFoundCount = 0; @@ -74,7 +79,7 @@ class HaQrScanner extends LitElement { @@ -90,11 +95,22 @@ class HaQrScanner extends LitElement { ` : ""} ` - : html`${!window.isSecureContext - ? "You can only use your camera to scan a QR core when using HTTPS." - : "Your browser doesn't support QR scanning."}`}`; + : html` + ${!window.isSecureContext + ? this.localize("ui.components.qr-scanner.only_https_supported") + : this.localize("ui.components.qr-scanner.not_supported")} + +

${this.localize("ui.components.qr-scanner.manual_input")}

+
+ + ${this.localize("ui.common.submit")} +
`}`; } private async _loadQrScanner() { @@ -143,6 +159,23 @@ class HaQrScanner extends LitElement { fireEvent(this, "qr-code-scanned", { value: qrCodeString }); }; + private _manualKeyup(ev: KeyboardEvent) { + if (ev.key === "Enter") { + this._qrCodeScanned((ev.target as TextField).value); + } + } + + private _manualPaste(ev: ClipboardEvent) { + this._qrCodeScanned( + // @ts-ignore + (ev.clipboardData || window.clipboardData).getData("text") + ); + } + + private _manualSubmit() { + this._qrCodeScanned(this._manualInput!.value); + } + private _cameraChanged(ev: CustomEvent): void { this._qrScanner?.setCamera((ev.target as any).value); } @@ -162,6 +195,14 @@ class HaQrScanner extends LitElement { color: white; border-radius: 50%; } + .row { + display: flex; + align-items: center; + } + mwc-textfield { + flex: 1; + margin-right: 8px; + } `; } diff --git a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-add-node.ts b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-add-node.ts index cc4cdda74e..82a7ebda77 100644 --- a/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-add-node.ts +++ b/src/panels/config/integrations/integration-panels/zwave_js/dialog-zwave_js-add-node.ts @@ -178,7 +178,10 @@ class DialogZWaveJSAddNode extends LitElement { Search device ` : this._status === "qr_scan" - ? html`${this._error}` + : ""} + @@ -194,9 +197,9 @@ class DialogZWaveJSAddNode extends LitElement {

${ this._error - ? html`${this._error}` + ? html` + ${this._error} + ` : "" }
@@ -614,7 +617,6 @@ class DialogZWaveJSAddNode extends LitElement { ZWaveFeature.SmartStart ) ).supported; - this._supportsSmartStart = true; } private _startOver(_ev: Event) { diff --git a/src/translations/en.json b/src/translations/en.json index 96ebbaa632..eec89cb39c 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -291,6 +291,7 @@ "undo": "Undo", "move": "Move", "save": "Save", + "submit": "Submit", "rename": "Rename", "yes": "Yes", "no": "No", @@ -538,6 +539,13 @@ }, "attributes": { "expansion_header": "Attributes" + }, + "qr-scanner": { + "select_camera": "Select camera", + "only_https_supported": "You can only use your camera to scan a QR code when using HTTPS.", + "not_supported": "Your browser doesn't support QR scanning.", + "manual_input": "You can scan the QR code with another QR scanner and paste the code in the input below", + "enter_qr_code": "Enter QR code value" } }, "dialogs": { @@ -2920,8 +2928,6 @@ "qr_code": "QR Code", "qr_code_paragraph": "If your device supports SmartStart you can scan the QR code for easy pairing.", "scan_qr_code": "Scan QR code", - "enter_qr_code": "Enter QR code value", - "select_camera": "Select camera", "inclusion_failed": "The device could not be added.", "check_logs": "Please check the logs for more information.", "inclusion_finished": "The device has been added.", From 2890192c054fdb48fe5d2181d73ef94900ee7fc7 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Sat, 11 Dec 2021 17:13:24 +0100 Subject: [PATCH 08/11] Fix formfield label touch (#10867) --- src/components/ha-formfield.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/components/ha-formfield.ts b/src/components/ha-formfield.ts index e0452e0db7..7ca076e7ea 100644 --- a/src/components/ha-formfield.ts +++ b/src/components/ha-formfield.ts @@ -1,10 +1,28 @@ import { Formfield } from "@material/mwc-formfield"; import { css, CSSResultGroup } from "lit"; import { customElement } from "lit/decorators"; +import { fireEvent } from "../common/dom/fire_event"; @customElement("ha-formfield") // @ts-expect-error export class HaFormfield extends Formfield { + protected _labelClick() { + const input = this.input; + if (input) { + input.focus(); + switch (input.tagName) { + case "HA-CHECKBOX": + case "HA-RADIO": + (input as any).checked = !(input as any).checked; + fireEvent(input, "change"); + break; + default: + input.click(); + break; + } + } + } + protected static get styles(): CSSResultGroup { return [ Formfield.styles, From b730676914a33c3b848a3f89d979e011e04c0dbf Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Sat, 11 Dec 2021 17:13:43 +0100 Subject: [PATCH 09/11] Fix translations cover controls (#10868) --- src/components/ha-cover-controls.ts | 6 +++--- src/components/ha-cover-tilt-controls.ts | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/ha-cover-controls.ts b/src/components/ha-cover-controls.ts index 9f28b010d9..73a1acbc5d 100644 --- a/src/components/ha-cover-controls.ts +++ b/src/components/ha-cover-controls.ts @@ -35,7 +35,7 @@ class HaCoverControls extends LitElement { hidden: !supportsOpen(this.stateObj), })} .label=${this.hass.localize( - "ui.dialogs.more_info_control.open_cover" + "ui.dialogs.more_info_control.cover.open_cover" )} @click=${this._onOpenTap} .disabled=${this._computeOpenDisabled()} @@ -47,7 +47,7 @@ class HaCoverControls extends LitElement { hidden: !supportsStop(this.stateObj), })} .label=${this.hass.localize( - "ui.dialogs.more_info_control.stop_cover" + "ui.dialogs.more_info_control.cover.stop_cover" )} .path=${mdiStop} @click=${this._onStopTap} @@ -58,7 +58,7 @@ class HaCoverControls extends LitElement { hidden: !supportsClose(this.stateObj), })} .label=${this.hass.localize( - "ui.dialogs.more_info_control.close_cover" + "ui.dialogs.more_info_control.cover.close_cover" )} @click=${this._onCloseTap} .disabled=${this._computeClosedDisabled()} diff --git a/src/components/ha-cover-tilt-controls.ts b/src/components/ha-cover-tilt-controls.ts index dac778f0ad..d0ce147f89 100644 --- a/src/components/ha-cover-tilt-controls.ts +++ b/src/components/ha-cover-tilt-controls.ts @@ -30,7 +30,7 @@ class HaCoverTiltControls extends LitElement { invisible: !supportsOpenTilt(this.stateObj), })} .label=${this.hass.localize( - "ui.dialogs.more_info_control.open_tilt_cover" + "ui.dialogs.more_info_control.cover.open_tilt_cover" )} .path=${mdiArrowTopRight} @click=${this._onOpenTiltTap} @@ -40,7 +40,9 @@ class HaCoverTiltControls extends LitElement { class=${classMap({ invisible: !supportsStopTilt(this.stateObj), })} - .label=${this.hass.localize("ui.dialogs.more_info_control.stop_cover")} + .label=${this.hass.localize( + "ui.dialogs.more_info_control.cover.stop_cover" + )} .path=${mdiStop} @click=${this._onStopTiltTap} .disabled=${this.stateObj.state === UNAVAILABLE} @@ -50,7 +52,7 @@ class HaCoverTiltControls extends LitElement { invisible: !supportsCloseTilt(this.stateObj), })} .label=${this.hass.localize( - "ui.dialogs.more_info_control.close_tilt_cover" + "ui.dialogs.more_info_control.cover.close_tilt_cover" )} .path=${mdiArrowBottomLeft} @click=${this._onCloseTiltTap} From 35e9687170876ddf4103c422a0099dc980566585 Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Sat, 11 Dec 2021 17:15:16 +0100 Subject: [PATCH 10/11] Replace `mwc-icon-button` with `ha-icon-button` in automation picker (#10858) --- src/components/ha-button-related-filter-menu.ts | 1 + src/components/ha-icon-overflow-menu.ts | 12 +++++------- src/translations/en.json | 2 ++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/components/ha-button-related-filter-menu.ts b/src/components/ha-button-related-filter-menu.ts index afbfff1966..fb65469e12 100644 --- a/src/components/ha-button-related-filter-menu.ts +++ b/src/components/ha-button-related-filter-menu.ts @@ -56,6 +56,7 @@ export class HaRelatedFilterButtonMenu extends LitElement { return html` + ? html` ` : html` - - + ${this.items.map((item) => item.narrowOnly ? "" @@ -70,13 +69,12 @@ export class HaIconOverflowMenu extends LitElement { ${item.tooltip} ` : ""} - - - + >
` )} `} diff --git a/src/translations/en.json b/src/translations/en.json index eec89cb39c..e423ddcf10 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -298,6 +298,7 @@ "not_now": "Not now", "skip": "Skip", "menu": "Menu", + "overflow_menu": "Overflow menu", "help": "Help", "successfully_saved": "Successfully saved", "successfully_deleted": "Successfully deleted", @@ -422,6 +423,7 @@ } }, "related-filter-menu": { + "filter": "Filter", "filter_by_entity": "Filter by entity", "filter_by_device": "Filter by device", "filter_by_area": "Filter by area", From 2b0359edba777581e16112c11cf7c5a94dfe0b79 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Sat, 11 Dec 2021 17:15:38 +0100 Subject: [PATCH 11/11] Bumped version to 20211211.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 75612bd2c5..ddadce10c4 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name="home-assistant-frontend", - version="20211209.0", + version="20211211.0", description="The Home Assistant frontend", url="https://github.com/home-assistant/frontend", author="The Home Assistant Authors",