From d0d0c44ec7914058814f2c1ce2e7317f5f98ac83 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 2 Mar 2022 17:50:01 +0100 Subject: [PATCH 01/13] Fix quickbar overlaying, fix click handling (#11900) --- src/dialogs/quick-bar/ha-quick-bar.ts | 57 ++++++++++++++------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index 337855d71b..3a7b3aaa96 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -86,11 +86,11 @@ export class QuickBar extends LitElement { @state() private _search = ""; - @state() private _opened = false; + @state() private _open = false; @state() private _commandMode = false; - @state() private _done = false; + @state() private _opened = false; @state() private _narrow = false; @@ -109,12 +109,12 @@ export class QuickBar extends LitElement { "all and (max-width: 450px), all and (max-height: 500px)" ).matches; this._initializeItemsIfNeeded(); - this._opened = true; + this._open = true; } public closeDialog() { + this._open = false; this._opened = false; - this._done = false; this._focusSet = false; this._filter = ""; this._search = ""; @@ -133,7 +133,7 @@ export class QuickBar extends LitElement { ); protected render() { - if (!this._opened) { + if (!this._open) { return html``; } @@ -218,24 +218,26 @@ export class QuickBar extends LitElement { ` : html` - - + ${this._opened + ? html` + ` + : ""} `} ${this._hint ? html`
${this._hint}
` : ""} @@ -252,9 +254,7 @@ export class QuickBar extends LitElement { } private _handleOpened() { - this.updateComplete.then(() => { - this._done = true; - }); + this._opened = true; } private async _handleRangeChanged(e) { @@ -454,9 +454,10 @@ export class QuickBar extends LitElement { } private _handleItemClick(ev) { + const listItem = ev.target.closest("mwc-list-item"); this.processItemAndCloseDialog( - (ev.target as any).item, - Number((ev.target as HTMLElement).getAttribute("index")) + listItem.item, + Number(listItem.getAttribute("index")) ); } From 87c74078575f5b6b663ca212961660c4042554c4 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 3 Mar 2022 13:55:40 +0100 Subject: [PATCH 02/13] Convert objects to string in config flow error (#11908) --- src/dialogs/config-flow/dialog-data-entry-flow.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/dialogs/config-flow/dialog-data-entry-flow.ts b/src/dialogs/config-flow/dialog-data-entry-flow.ts index 29bea7491e..6a128d081a 100644 --- a/src/dialogs/config-flow/dialog-data-entry-flow.ts +++ b/src/dialogs/config-flow/dialog-data-entry-flow.ts @@ -117,13 +117,17 @@ class DataEntryFlowDialog extends LitElement { ); } catch (err: any) { this.closeDialog(); + let message = err.message || err.body || "Unknown error"; + if (typeof message !== "string") { + message = JSON.stringify(message); + } showAlertDialog(this, { title: this.hass.localize( "ui.panel.config.integrations.config_flow.error" ), text: `${this.hass.localize( "ui.panel.config.integrations.config_flow.could_not_load" - )}: ${err.message || err.body}`, + )}: ${message}`, }); return; } From a040e1d5e0a022579eb7d08f2a9276b375c4c80a Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 4 Mar 2022 23:15:10 +0100 Subject: [PATCH 03/13] Convert lovelace config dialogs to ha-form (#11910) --- .../dialog-lovelace-dashboard-detail.ts | 290 ++++++++---------- .../dialog-lovelace-resource-detail.ts | 227 +++++++------- 2 files changed, 240 insertions(+), 277 deletions(-) diff --git a/src/panels/config/lovelace/dashboards/dialog-lovelace-dashboard-detail.ts b/src/panels/config/lovelace/dashboards/dialog-lovelace-dashboard-detail.ts index 39b449d3d7..75db9e031c 100644 --- a/src/panels/config/lovelace/dashboards/dialog-lovelace-dashboard-detail.ts +++ b/src/panels/config/lovelace/dashboards/dialog-lovelace-dashboard-detail.ts @@ -1,20 +1,18 @@ import "@material/mwc-button/mwc-button"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; +import memoizeOne from "memoize-one"; +import { fireEvent } from "../../../../common/dom/fire_event"; import { slugify } from "../../../../common/string/slugify"; -import { computeRTLDirection } from "../../../../common/util/compute_rtl"; import { createCloseHeading } from "../../../../components/ha-dialog"; -import "../../../../components/ha-formfield"; -import "../../../../components/ha-icon-picker"; -import "../../../../components/ha-switch"; -import type { HaSwitch } from "../../../../components/ha-switch"; +import "../../../../components/ha-form/ha-form"; +import { HaFormSchema } from "../../../../components/ha-form/types"; +import { CoreFrontendUserData } from "../../../../data/frontend"; import { LovelaceDashboard, LovelaceDashboardCreateParams, - LovelaceDashboardMutableParams, } from "../../../../data/lovelace"; import { DEFAULT_PANEL, setDefaultPanel } from "../../../../data/panel"; -import { PolymerChangedEvent } from "../../../../polymer-types"; import { haStyleDialog } from "../../../../resources/styles"; import { HomeAssistant } from "../../../../types"; import { LovelaceDashboardDetailsDialogParams } from "./show-dialog-lovelace-dashboard-detail"; @@ -25,62 +23,54 @@ export class DialogLovelaceDashboardDetail extends LitElement { @state() private _params?: LovelaceDashboardDetailsDialogParams; - @state() private _urlPath!: LovelaceDashboard["url_path"]; + @state() private _urlPathChanged = false; - @state() private _showInSidebar!: boolean; + @state() private _data?: Partial; - @state() private _icon!: string; - - @state() private _title!: string; - - @state() - private _requireAdmin!: LovelaceDashboard["require_admin"]; - - @state() private _error?: string; + @state() private _error?: Record; @state() private _submitting = false; - public async showDialog( - params: LovelaceDashboardDetailsDialogParams - ): Promise { + public showDialog(params: LovelaceDashboardDetailsDialogParams): void { this._params = params; this._error = undefined; - this._urlPath = this._params.urlPath || ""; + this._urlPathChanged = false; if (this._params.dashboard) { - this._showInSidebar = !!this._params.dashboard.show_in_sidebar; - this._icon = this._params.dashboard.icon || ""; - this._title = this._params.dashboard.title || ""; - this._requireAdmin = this._params.dashboard.require_admin || false; + this._data = this._params.dashboard; } else { - this._showInSidebar = true; - this._icon = ""; - this._title = ""; - this._requireAdmin = false; + this._data = { + show_in_sidebar: true, + icon: "", + title: "", + require_admin: false, + mode: "storage", + }; } - await this.updateComplete; + } + + public closeDialog(): void { + this._params = undefined; + this._data = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); } protected render(): TemplateResult { - if (!this._params) { + if (!this._params || !this._data) { return html``; } const defaultPanelUrlPath = this.hass.defaultPanel; - const urlInvalid = - this._params.urlPath !== "lovelace" && - !/^[a-zA-Z0-9_-]+-[a-zA-Z0-9_-]+$/.test(this._urlPath); - const titleInvalid = !this._title.trim(); - const dir = computeRTLDirection(this.hass); + const titleInvalid = !this._data.title || !this._data.title.trim(); return html` ${this._error} ` - : ""} -
- - - ${!this._params.dashboard && this.hass.userData?.showAdvanced - ? html` - - ` - : ""} -
- - - - -
-
- - - - -
-
+ `} ${this._params.urlPath @@ -206,7 +134,9 @@ export class DialogLovelaceDashboardDetail extends LitElement { ${this._params.urlPath @@ -223,41 +153,97 @@ export class DialogLovelaceDashboardDetail extends LitElement { `; } - private _urlChanged(ev: PolymerChangedEvent) { - this._error = undefined; - this._urlPath = ev.detail.value; - } + private _schema = memoizeOne( + ( + params: LovelaceDashboardDetailsDialogParams, + userData: CoreFrontendUserData | null | undefined + ) => + [ + { + name: "title", + required: true, + selector: { + text: {}, + }, + }, + { + name: "icon", + required: true, + selector: { + icon: {}, + }, + }, + !params.dashboard && + userData?.showAdvanced && { + name: "url_path", + required: true, + selector: { text: {} }, + }, + { + name: "require_admin", + required: true, + selector: { + boolean: {}, + }, + }, + { + name: "show_in_sidebar", + required: true, + selector: { + boolean: {}, + }, + }, + ].filter(Boolean) + ); - private _iconChanged(ev: PolymerChangedEvent) { - this._error = undefined; - this._icon = ev.detail.value; - } + private _computeLabel = (entry: HaFormSchema): string => + this.hass.localize( + `ui.panel.config.lovelace.dashboards.detail.${ + entry.name === "show_in_sidebar" + ? "show_sidebar" + : entry.name === "url_path" + ? "url" + : entry.name + }` + ); - private _titleChanged(ev: PolymerChangedEvent) { + private _valueChanged(ev: CustomEvent) { this._error = undefined; - this._title = ev.detail.value; - if (!this.hass.userData?.showAdvanced) { - this._fillUrlPath(); + const value = ev.detail.value; + if (value.url_path !== this._data?.url_path) { + this._urlPathChanged = true; + if ( + !value.url_path || + value.url_path === "lovelace" || + !/^[a-zA-Z0-9_-]+-[a-zA-Z0-9_-]+$/.test(value.url_path) + ) { + this._error = { + url_path: this.hass.localize( + "ui.panel.config.lovelace.dashboards.detail.url_error_msg" + ), + }; + } + } + if (value.title !== this._data?.title) { + this._data = value; + this._fillUrlPath(value.title); + } else { + this._data = value; } } - private _fillUrlPath() { - if ((this.hass.userData?.showAdvanced && this._urlPath) || !this._title) { + private _fillUrlPath(title: string) { + if ((this.hass.userData?.showAdvanced && this._urlPathChanged) || !title) { return; } - const slugifyTitle = slugify(this._title, "-"); - this._urlPath = slugifyTitle.includes("-") - ? slugifyTitle - : `lovelace-${slugifyTitle}`; - } - - private _showSidebarChanged(ev: Event) { - this._showInSidebar = (ev.target as HaSwitch).checked; - } - - private _requireAdminChanged(ev: Event) { - this._requireAdmin = (ev.target as HaSwitch).checked; + const slugifyTitle = slugify(title, "-"); + this._data = { + ...this._data, + url_path: slugifyTitle.includes("-") + ? slugifyTitle + : `lovelace-${slugifyTitle}`, + }; } private _toggleDefault() { @@ -273,29 +259,20 @@ export class DialogLovelaceDashboardDetail extends LitElement { private async _updateDashboard() { if (this._params?.urlPath && !this._params.dashboard?.id) { - this._close(); + this.closeDialog(); } this._submitting = true; try { - const values: Partial = { - require_admin: this._requireAdmin, - show_in_sidebar: this._showInSidebar, - icon: this._icon || undefined, - title: this._title, - }; if (this._params!.dashboard) { - await this._params!.updateDashboard(values); + await this._params!.updateDashboard(this._data as LovelaceDashboard); } else { - (values as LovelaceDashboardCreateParams).url_path = - this._urlPath.trim(); - (values as LovelaceDashboardCreateParams).mode = "storage"; await this._params!.createDashboard( - values as LovelaceDashboardCreateParams + this._data as LovelaceDashboardCreateParams ); } - this._close(); + this.closeDialog(); } catch (err: any) { - this._error = err?.message || "Unknown error"; + this._error = { base: err?.message || "Unknown error" }; } finally { this._submitting = false; } @@ -305,26 +282,15 @@ export class DialogLovelaceDashboardDetail extends LitElement { this._submitting = true; try { if (await this._params!.removeDashboard()) { - this._close(); + this.closeDialog(); } } finally { this._submitting = false; } } - private _close(): void { - this._params = undefined; - } - static get styles(): CSSResultGroup { - return [ - haStyleDialog, - css` - ha-switch { - padding: 16px 0; - } - `, - ]; + return [haStyleDialog, css``]; } } diff --git a/src/panels/config/lovelace/resources/dialog-lovelace-resource-detail.ts b/src/panels/config/lovelace/resources/dialog-lovelace-resource-detail.ts index eb2ebe92d3..283d1f2986 100644 --- a/src/panels/config/lovelace/resources/dialog-lovelace-resource-detail.ts +++ b/src/panels/config/lovelace/resources/dialog-lovelace-resource-detail.ts @@ -1,21 +1,20 @@ import "@material/mwc-button/mwc-button"; -import "@material/mwc-list/mwc-list-item"; -import "@polymer/paper-input/paper-input"; -import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; +import { CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; -import { stopPropagation } from "../../../../common/dom/stop_propagation"; +import memoizeOne from "memoize-one"; +import { fireEvent } from "../../../../common/dom/fire_event"; import { createCloseHeading } from "../../../../components/ha-dialog"; -import "../../../../components/ha-select"; -import { - LovelaceResource, - LovelaceResourcesMutableParams, -} from "../../../../data/lovelace"; -import { PolymerChangedEvent } from "../../../../polymer-types"; +import "../../../../components/ha-form/ha-form"; +import { HaFormSchema } from "../../../../components/ha-form/types"; +import { LovelaceResourcesMutableParams } from "../../../../data/lovelace"; import { haStyleDialog } from "../../../../resources/styles"; import { HomeAssistant } from "../../../../types"; import { LovelaceResourceDetailsDialogParams } from "./show-dialog-lovelace-resource-detail"; -const detectResourceType = (url: string) => { +const detectResourceType = (url?: string) => { + if (!url) { + return undefined; + } const ext = url.split(".").pop() || ""; if (ext === "css") { @@ -35,38 +34,41 @@ export class DialogLovelaceResourceDetail extends LitElement { @state() private _params?: LovelaceResourceDetailsDialogParams; - @state() private _url!: LovelaceResource["url"]; + @state() private _data?: Partial; - @state() private _type?: LovelaceResource["type"]; - - @state() private _error?: string; + @state() private _error?: Record; @state() private _submitting = false; - public async showDialog( - params: LovelaceResourceDetailsDialogParams - ): Promise { + public showDialog(params: LovelaceResourceDetailsDialogParams): void { this._params = params; this._error = undefined; if (this._params.resource) { - this._url = this._params.resource.url || ""; - this._type = this._params.resource.type || undefined; + this._data = { + url: this._params.resource.url, + res_type: this._params.resource.type, + }; } else { - this._url = ""; - this._type = undefined; + this._data = { + url: "", + }; } - await this.updateComplete; + } + + public closeDialog(): void { + this._params = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); } protected render(): TemplateResult { if (!this._params) { return html``; } - const urlInvalid = this._url.trim() === ""; + const urlInvalid = !this._data?.url || this._data.url.trim() === ""; return html`
- ${this._error ? html`
${this._error}
` : ""} -
-

- ${this.hass!.localize( - "ui.panel.config.lovelace.resources.detail.warning_header" - )} -

+ ${this.hass!.localize( "ui.panel.config.lovelace.resources.detail.warning_text" )} - -
- - - ${this.hass!.localize( - "ui.panel.config.lovelace.resources.types.module" - )} - - ${this._type === "js" - ? html` - - ${this.hass!.localize( - "ui.panel.config.lovelace.resources.types.js" - )} - - ` - : ""} - - ${this.hass!.localize( - "ui.panel.config.lovelace.resources.types.css" - )} - - ${this._type === "html" - ? html` - - ${this.hass!.localize( - "ui.panel.config.lovelace.resources.types.html" - )} - - ` - : ""} - -
+ + +
${this._params.resource ? html` @@ -159,7 +118,7 @@ export class DialogLovelaceResourceDetail extends LitElement { ${this._params.resource ? this.hass!.localize( @@ -173,37 +132,86 @@ export class DialogLovelaceResourceDetail extends LitElement { `; } - private _urlChanged(ev: PolymerChangedEvent) { - this._error = undefined; - this._url = ev.detail.value; - if (!this._type) { - this._type = detectResourceType(this._url); + private _schema = memoizeOne((data) => [ + { + name: "url", + required: true, + selector: { + text: {}, + }, + }, + { + name: "res_type", + required: true, + selector: { + select: { + options: [ + { + value: "module", + label: this.hass!.localize( + "ui.panel.config.lovelace.resources.types.module" + ), + }, + { + value: "css", + label: this.hass!.localize( + "ui.panel.config.lovelace.resources.types.css" + ), + }, + data.type === "js" && { + value: "js", + label: this.hass!.localize( + "ui.panel.config.lovelace.resources.types.js" + ), + }, + data.type === "html" && { + value: "html", + label: this.hass!.localize( + "ui.panel.config.lovelace.resources.types.html" + ), + }, + ].filter(Boolean), + }, + }, + }, + ]); + + private _computeLabel = (entry: HaFormSchema): string => + this.hass.localize( + `ui.panel.config.lovelace.resources.detail.${entry.name}` + ); + + private _valueChanged(ev: CustomEvent) { + this._data = ev.detail.value; + if (!this._data!.res_type) { + const type = detectResourceType(this._data!.url); + if (!type) { + return; + } + this._data = { + ...this._data, + res_type: type, + }; } } - private _typeChanged(ev) { - this._type = ev.target.value; - } - private async _updateResource() { - if (!this._type) { + if (!this._data?.res_type) { return; } this._submitting = true; try { - const values: LovelaceResourcesMutableParams = { - url: this._url.trim(), - res_type: this._type, - }; if (this._params!.resource) { - await this._params!.updateResource(values); + await this._params!.updateResource(this._data!); } else { - await this._params!.createResource(values); + await this._params!.createResource( + this._data! as LovelaceResourcesMutableParams + ); } this._params = undefined; } catch (err: any) { - this._error = err?.message || "Unknown error"; + this._error = { base: err?.message || "Unknown error" }; } finally { this._submitting = false; } @@ -213,26 +221,15 @@ export class DialogLovelaceResourceDetail extends LitElement { this._submitting = true; try { if (await this._params!.removeResource()) { - this._close(); + this.closeDialog(); } } finally { this._submitting = false; } } - private _close(): void { - this._params = undefined; - } - static get styles(): CSSResultGroup { - return [ - haStyleDialog, - css` - .warning { - color: var(--error-color); - } - `, - ]; + return haStyleDialog; } } From 7c94ced30341536ddc53e1e45e0604f6ae293a2c Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 4 Mar 2022 14:31:11 -0800 Subject: [PATCH 04/13] Guard setting up config flow for an unsupported domain (#11937) --- .../config-flow/dialog-data-entry-flow.ts | 13 ++++++++++--- .../integrations/ha-config-integrations.ts | 19 ++++++++++++++++++- src/translations/en.json | 1 + 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/dialogs/config-flow/dialog-data-entry-flow.ts b/src/dialogs/config-flow/dialog-data-entry-flow.ts index 6a128d081a..6fbab75c74 100644 --- a/src/dialogs/config-flow/dialog-data-entry-flow.ts +++ b/src/dialogs/config-flow/dialog-data-entry-flow.ts @@ -377,13 +377,20 @@ class DataEntryFlowDialog extends LitElement { step = await this._params!.flowConfig.createFlow(this.hass, handler); } catch (err: any) { this.closeDialog(); + const message = + err?.status_code === 404 + ? this.hass.localize( + "ui.panel.config.integrations.config_flow.no_config_flow" + ) + : `${this.hass.localize( + "ui.panel.config.integrations.config_flow.could_not_load" + )}: ${err?.body?.message || err?.message}`; + showAlertDialog(this, { title: this.hass.localize( "ui.panel.config.integrations.config_flow.error" ), - text: `${this.hass.localize( - "ui.panel.config.integrations.config_flow.could_not_load" - )}: ${err.message || err.body}`, + text: message, }); return; } finally { diff --git a/src/panels/config/integrations/ha-config-integrations.ts b/src/panels/config/integrations/ha-config-integrations.ts index f58a797a36..5255d1197e 100644 --- a/src/panels/config/integrations/ha-config-integrations.ts +++ b/src/panels/config/integrations/ha-config-integrations.ts @@ -30,6 +30,7 @@ import "../../../components/ha-check-list-item"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { ConfigEntry, getConfigEntries } from "../../../data/config_entries"; import { + getConfigFlowHandlers, getConfigFlowInProgressCollection, localizeConfigFlowTitle, subscribeConfigFlowInProgress, @@ -51,7 +52,10 @@ import { } from "../../../data/integration"; import { scanUSBDevices } from "../../../data/usb"; import { showConfigFlowDialog } from "../../../dialogs/config-flow/show-dialog-config-flow"; -import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box"; +import { + showAlertDialog, + showConfirmationDialog, +} from "../../../dialogs/generic/show-dialog-box"; import "../../../layouts/hass-loading-screen"; import "../../../layouts/hass-tabs-subpage"; import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; @@ -652,6 +656,19 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { if (!domain) { return; } + const handlers = await getConfigFlowHandlers(this.hass); + + if (!handlers.includes(domain)) { + showAlertDialog(this, { + title: this.hass.localize( + "ui.panel.config.integrations.config_flow.error" + ), + text: this.hass.localize( + "ui.panel.config.integrations.config_flow.no_config_flow" + ), + }); + return; + } const localize = await localizePromise; if ( !(await showConfirmationDialog(this, { diff --git a/src/translations/en.json b/src/translations/en.json index d1ec5a56b3..e25991e80f 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2605,6 +2605,7 @@ "finish": "Finish", "submit": "Submit", "next": "Next", + "no_config_flow": "This integration does not support configuration via the UI. If you followed this link from the Home Assistant website, make sure you run the latest version of Home Assistant.", "not_all_required_fields": "Not all required fields are filled in.", "error_saving_area": "Error saving area: {error}", "created_config": "Created configuration for {name}.", From 8e51878b6d3d69618b059ee96540145a78055cdd Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 7 Mar 2022 12:45:39 +0100 Subject: [PATCH 05/13] Convert inputs (#11907) * Convert inputs * Update dialog-thingtalk.ts * imports --- hassio/src/components/hassio-upload-backup.ts | 1 - src/components/ha-date-input.ts | 2 +- src/components/ha-textfield.ts | 11 +++ src/components/search-input.ts | 2 +- src/dialogs/quick-bar/ha-quick-bar.ts | 2 +- .../ha-voice-command-dialog.ts | 29 ++++--- .../automation/blueprint-automation-editor.ts | 84 +++++++++++++------ .../automation/thingtalk/dialog-thingtalk.ts | 16 ++-- .../types/ha-automation-trigger-webhook.ts | 2 +- .../dialog-manage-cloudhook.ts | 40 ++++----- .../dialogs/dialog-energy-gas-settings.ts | 19 ++--- .../dialog-energy-grid-flow-settings.ts | 22 ++--- .../zwave_js/dialog-zwave_js-add-node.ts | 24 +++--- .../zwave_js/zwave_js-node-config.ts | 9 +- .../config/script/blueprint-script-editor.ts | 4 +- .../components/hui-input-list-editor.ts | 29 ++++--- .../config-elements/hui-map-card-editor.ts | 7 +- .../hui-picture-card-editor.ts | 1 - 18 files changed, 168 insertions(+), 136 deletions(-) diff --git a/hassio/src/components/hassio-upload-backup.ts b/hassio/src/components/hassio-upload-backup.ts index ae19a12c81..d40345522e 100644 --- a/hassio/src/components/hassio-upload-backup.ts +++ b/hassio/src/components/hassio-upload-backup.ts @@ -1,5 +1,4 @@ import { mdiFolderUpload } from "@mdi/js"; -import "@polymer/paper-input/paper-input-container"; import { html, LitElement, TemplateResult } from "lit"; import { customElement, state } from "lit/decorators"; import { fireEvent } from "../../../src/common/dom/fire_event"; diff --git a/src/components/ha-date-input.ts b/src/components/ha-date-input.ts index 42308ee6c7..7575e3bcef 100644 --- a/src/components/ha-date-input.ts +++ b/src/components/ha-date-input.ts @@ -41,7 +41,7 @@ export class HaDateInput extends LitElement { return html` diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index 3a7b3aaa96..6135b6f4fd 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -162,7 +162,7 @@ export class QuickBar extends LitElement { "ui.dialogs.quick-bar.filter_placeholder" )} .value=${this._commandMode ? `>${this._search}` : this._search} - .icon=${true} + icon .iconTrailing=${this._search !== undefined || this._narrow} @input=${this._handleSearchChange} @keydown=${this._handleInputKeyDown} diff --git a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts index 4c8fa20780..d05e441781 100644 --- a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts +++ b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts @@ -1,7 +1,6 @@ /* eslint-disable lit/prefer-static-styles */ +import "@material/mwc-button/mwc-button"; import { mdiMicrophone } from "@mdi/js"; -import "@polymer/paper-input/paper-input"; -import type { PaperInputElement } from "@polymer/paper-input/paper-input"; import { css, CSSResultGroup, @@ -10,12 +9,16 @@ import { PropertyValues, TemplateResult, } from "lit"; -import { customElement, property, state, query } from "lit/decorators"; +import { customElement, property, query, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { fireEvent } from "../../common/dom/fire_event"; import { SpeechRecognition } from "../../common/dom/speech-recognition"; import { uid } from "../../common/util/uid"; +import "../../components/ha-dialog"; +import type { HaDialog } from "../../components/ha-dialog"; import "../../components/ha-icon-button"; +import "../../components/ha-textfield"; +import type { HaTextField } from "../../components/ha-textfield"; import { AgentInfo, getAgentInfo, @@ -24,9 +27,6 @@ import { } from "../../data/conversation"; import { haStyleDialog } from "../../resources/styles"; import type { HomeAssistant } from "../../types"; -import "../../components/ha-dialog"; -import type { HaDialog } from "../../components/ha-dialog"; -import "@material/mwc-button/mwc-button"; interface Message { who: string; @@ -127,18 +127,19 @@ export class HaVoiceCommandDialog extends LitElement { : ""}
- ${SpeechRecognition ? html` - + ${this.results ? html`
@@ -155,7 +156,7 @@ export class HaVoiceCommandDialog extends LitElement { ` : ""} - + ${this._agentInfo && this._agentInfo.attribution ? html`
- - - + + ${this._showDescription + ? html` + + ` + : html` + + `}
${this.stateObj ? html` @@ -173,15 +199,14 @@ export class HaBlueprintAutomationEditor extends LitElement { value?.default} @value-changed=${this._inputChanged} >` - : html``} + @input=${this._inputChanged} + >`} ` ) : html`

@@ -221,7 +246,7 @@ export class HaBlueprintAutomationEditor extends LitElement { ev.stopPropagation(); const target = ev.target as any; const key = target.key; - const value = ev.detail.value; + const value = ev.detail?.value || target.value; if ( (this.config.use_blueprint.input && this.config.use_blueprint.input[key] === value) || @@ -262,6 +287,10 @@ export class HaBlueprintAutomationEditor extends LitElement { }); } + private _addDescription() { + this._showDescription = true; + } + static get styles(): CSSResultGroup { return [ haStyle, @@ -273,9 +302,16 @@ export class HaBlueprintAutomationEditor extends LitElement { .padding { padding: 16px; } + .link-button-row { + padding: 14px; + } .blueprint-picker-container { padding: 0 16px 16px; } + ha-textarea, + ha-textfield { + display: block; + } h3 { margin: 16px; } @@ -292,9 +328,7 @@ export class HaBlueprintAutomationEditor extends LitElement { --paper-time-input-justify-content: flex-end; border-top: 1px solid var(--divider-color); } - :host(:not([narrow])) ha-settings-row paper-input { - width: 60%; - } + :host(:not([narrow])) ha-settings-row ha-textfield, :host(:not([narrow])) ha-settings-row ha-selector { width: 60%; } diff --git a/src/panels/config/automation/thingtalk/dialog-thingtalk.ts b/src/panels/config/automation/thingtalk/dialog-thingtalk.ts index 46cc842c5a..8eae2ce4b6 100644 --- a/src/panels/config/automation/thingtalk/dialog-thingtalk.ts +++ b/src/panels/config/automation/thingtalk/dialog-thingtalk.ts @@ -1,10 +1,11 @@ import "@material/mwc-button"; -import "@polymer/paper-input/paper-input"; -import type { PaperInputElement } from "@polymer/paper-input/paper-input"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; -import { customElement, property, state, query } from "lit/decorators"; +import { customElement, property, query, state } from "lit/decorators"; import { fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/ha-circular-progress"; +import "../../../../components/ha-dialog"; +import "../../../../components/ha-textfield"; +import type { HaTextField } from "../../../../components/ha-textfield"; import type { AutomationConfig } from "../../../../data/automation"; import { convertThingTalk } from "../../../../data/cloud"; import { haStyle, haStyleDialog } from "../../../../resources/styles"; @@ -12,7 +13,6 @@ import type { HomeAssistant } from "../../../../types"; import "./ha-thingtalk-placeholders"; import type { PlaceholderValues } from "./ha-thingtalk-placeholders"; import type { ThingtalkDialogParams } from "./show-dialog-thingtalk"; -import "../../../../components/ha-dialog"; export interface Placeholder { name: string; @@ -38,7 +38,7 @@ class DialogThingtalk extends LitElement { @state() private _placeholders?: PlaceholderContainer; - @query("#input") private _input?: PaperInputElement; + @query("#input") private _input?: HaTextField; private _value?: string; @@ -58,7 +58,7 @@ class DialogThingtalk extends LitElement { this._placeholders = undefined; this._params = undefined; if (this._input) { - this._input.value = null; + this._input.value = ""; } fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -127,13 +127,13 @@ class DialogThingtalk extends LitElement { - + > diff --git a/src/panels/config/cloud/dialog-manage-cloudhook/dialog-manage-cloudhook.ts b/src/panels/config/cloud/dialog-manage-cloudhook/dialog-manage-cloudhook.ts index b018af2959..1dc48f780f 100644 --- a/src/panels/config/cloud/dialog-manage-cloudhook/dialog-manage-cloudhook.ts +++ b/src/panels/config/cloud/dialog-manage-cloudhook/dialog-manage-cloudhook.ts @@ -1,11 +1,12 @@ import "@material/mwc-button"; -import "@polymer/paper-input/paper-input"; -import type { PaperInputElement } from "@polymer/paper-input/paper-input"; import { css, CSSResultGroup, html, LitElement } from "lit"; -import { state } from "lit/decorators"; +import { query, state } from "lit/decorators"; import { fireEvent } from "../../../../common/dom/fire_event"; +import { copyToClipboard } from "../../../../common/util/copy-clipboard"; +import type { HaTextField } from "../../../../components/ha-textfield"; +import "../../../../components/ha-textfield"; import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box"; -import { haStyle } from "../../../../resources/styles"; +import { haStyle, haStyleDialog } from "../../../../resources/styles"; import { HomeAssistant } from "../../../../types"; import { documentationUrl } from "../../../../util/documentation-url"; import { WebhookDialogParams } from "./show-dialog-manage-cloudhook"; @@ -17,6 +18,8 @@ export class DialogManageCloudhook extends LitElement { @state() private _params?: WebhookDialogParams; + @query("ha-textfield") _input!: HaTextField; + public showDialog(params: WebhookDialogParams) { this._params = params; } @@ -53,12 +56,12 @@ export class DialogManageCloudhook extends LitElement { "ui.panel.config.cloud.dialog_cloudhook.available_at" )}

- + >

${cloudhook.managed ? html` @@ -98,10 +101,6 @@ export class DialogManageCloudhook extends LitElement { `; } - private get _paperInput(): PaperInputElement { - return this.shadowRoot!.querySelector("paper-input")!; - } - private async _disableWebhook() { showConfirmationDialog(this, { text: this.hass!.localize( @@ -117,14 +116,10 @@ export class DialogManageCloudhook extends LitElement { } private _copyClipboard(ev: FocusEvent) { - // paper-input -> iron-input -> input - const paperInput = ev.currentTarget as PaperInputElement; - const input = (paperInput.inputElement as any) - .inputElement as HTMLInputElement; - input.setSelectionRange(0, input.value.length); + const textField = ev.currentTarget as HaTextField; try { - document.execCommand("copy"); - paperInput.label = this.hass!.localize( + copyToClipboard(textField.value); + textField.label = this.hass!.localize( "ui.panel.config.cloud.dialog_cloudhook.copied_to_clipboard" ); } catch (err: any) { @@ -133,18 +128,19 @@ export class DialogManageCloudhook extends LitElement { } private _restoreLabel() { - this._paperInput.label = inputLabel; + this._input.label = inputLabel; } static get styles(): CSSResultGroup { return [ haStyle, + haStyleDialog, css` ha-dialog { width: 650px; } - paper-input { - margin-top: -8px; + ha-textfield { + display: block; } button.link { color: var(--primary-color); diff --git a/src/panels/config/energy/dialogs/dialog-energy-gas-settings.ts b/src/panels/config/energy/dialogs/dialog-energy-gas-settings.ts index b180c5f151..8a3b57d427 100644 --- a/src/panels/config/energy/dialogs/dialog-energy-gas-settings.ts +++ b/src/panels/config/energy/dialogs/dialog-energy-gas-settings.ts @@ -19,6 +19,7 @@ import "../../../../components/entity/ha-statistic-picker"; import "../../../../components/entity/ha-entity-picker"; import "../../../../components/ha-radio"; import "../../../../components/ha-formfield"; +import "../../../../components/ha-textfield"; import type { HaRadio } from "../../../../components/ha-radio"; @customElement("dialog-energy-gas-settings") @@ -188,20 +189,19 @@ export class DialogEnergyGasSettings > ${this._costs === "number" - ? html` - ${this.hass.config.currency}/${unit} - ` + ` : ""} @@ -223,10 +223,10 @@ export class DialogEnergyGasSettings this._costs = input.value as any; } - private _numberPriceChanged(ev: CustomEvent) { + private _numberPriceChanged(ev) { this._source = { ...this._source!, - number_energy_price: Number(ev.detail.value), + number_energy_price: Number(ev.target.value), entity_energy_price: null, stat_cost: null, }; @@ -295,13 +295,10 @@ export class DialogEnergyGasSettings ha-formfield { display: block; } - ha-statistic-picker { - width: 100%; - } .price-options { display: block; padding-left: 52px; - margin-top: -16px; + margin-top: -8px; } `, ]; diff --git a/src/panels/config/energy/dialogs/dialog-energy-grid-flow-settings.ts b/src/panels/config/energy/dialogs/dialog-energy-grid-flow-settings.ts index d32e57f505..2599f61ee3 100644 --- a/src/panels/config/energy/dialogs/dialog-energy-grid-flow-settings.ts +++ b/src/panels/config/energy/dialogs/dialog-energy-grid-flow-settings.ts @@ -190,24 +190,21 @@ export class DialogEnergyGridFlowSettings > ${this._costs === "number" - ? html` - ${this.hass.localize( - `ui.panel.config.energy.grid.flow_dialog.${this._params.direction}.cost_number_suffix`, - { currency: this.hass.config.currency } - )} - ` + ` : ""} @@ -302,13 +299,10 @@ export class DialogEnergyGridFlowSettings ha-formfield { display: block; } - ha-statistic-picker { - width: 100%; - } .price-options { display: block; padding-left: 52px; - margin-top: -16px; + margin-top: -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 4c9603ba0a..c1a75807c7 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 @@ -1,7 +1,5 @@ import "@material/mwc-button/mwc-button"; import { mdiAlertCircle, mdiCheckCircle, mdiQrcodeScan } from "@mdi/js"; -import "@polymer/paper-input/paper-input"; -import type { PaperInputElement } from "@polymer/paper-input/paper-input"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, query, state } from "lit/decorators"; @@ -11,28 +9,30 @@ import { HaCheckbox } from "../../../../../components/ha-checkbox"; import "../../../../../components/ha-circular-progress"; import { createCloseHeading } from "../../../../../components/ha-dialog"; import "../../../../../components/ha-formfield"; +import "../../../../../components/ha-qr-scanner"; import "../../../../../components/ha-radio"; import "../../../../../components/ha-switch"; +import "../../../../../components/ha-textfield"; +import type { HaTextField } from "../../../../../components/ha-textfield"; import { - zwaveGrantSecurityClasses, InclusionStrategy, MINIMUM_QR_STRING_LENGTH, - zwaveParseQrCode, + PlannedProvisioningEntry, provisionZwaveSmartStartNode, QRProvisioningInformation, RequestedGrant, SecurityClass, stopZwaveInclusion, subscribeAddZwaveNode, + ZWaveFeature, + zwaveGrantSecurityClasses, + zwaveParseQrCode, zwaveSupportsFeature, zwaveValidateDskAndEnterPin, - ZWaveFeature, - PlannedProvisioningEntry, } from "../../../../../data/zwave_js"; import { haStyle, haStyleDialog } from "../../../../../resources/styles"; import { HomeAssistant } from "../../../../../types"; import { ZWaveJSAddNodeDialogParams } from "./show-dialog-zwave_js-add-node"; -import "../../../../../components/ha-qr-scanner"; export interface ZWaveJSAddNodeDevice { id: string; @@ -98,7 +98,7 @@ class DialogZWaveJSAddNode extends LitElement { this._startInclusion(); } - @query("#pin-input") private _pinInput?: PaperInputElement; + @query("#pin-input") private _pinInput?: HaTextField; protected render(): TemplateResult { if (!this._entryId) { @@ -202,12 +202,11 @@ class DialogZWaveJSAddNode extends LitElement { : "" }

- + > ${this._dsk}
${item.metadata.unit ? html`${item.metadata.unit}` : ""} - `; + `; } if (item.configuration_value_type === "enumerated") { @@ -492,7 +493,7 @@ class ZWaveJSNodeConfig extends SubscribeMixin(LitElement) { font-size: 1.3em; } - :host(:not([narrow])) ha-settings-row paper-input { + :host(:not([narrow])) ha-settings-row ha-textfield { width: 30%; text-align: right; } diff --git a/src/panels/config/script/blueprint-script-editor.ts b/src/panels/config/script/blueprint-script-editor.ts index 738fdb8419..6edae7d2cc 100644 --- a/src/panels/config/script/blueprint-script-editor.ts +++ b/src/panels/config/script/blueprint-script-editor.ts @@ -186,9 +186,7 @@ export class HaBlueprintScriptEditor extends LitElement { --paper-time-input-justify-content: flex-end; border-top: 1px solid var(--divider-color); } - :host(:not([narrow])) ha-settings-row paper-input { - width: 60%; - } + :host(:not([narrow])) ha-settings-row ha-textfield, :host(:not([narrow])) ha-settings-row ha-selector { width: 60%; } diff --git a/src/panels/lovelace/components/hui-input-list-editor.ts b/src/panels/lovelace/components/hui-input-list-editor.ts index fe53e72c11..a7c6ea75e0 100644 --- a/src/panels/lovelace/components/hui-input-list-editor.ts +++ b/src/panels/lovelace/components/hui-input-list-editor.ts @@ -1,11 +1,11 @@ import { mdiClose } from "@mdi/js"; -import "@polymer/paper-input/paper-input"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators"; import { fireEvent } from "../../../common/dom/fire_event"; import "../../../components/ha-icon-button"; import { HomeAssistant } from "../../../types"; import { EditorTarget } from "../editor/types"; +import "../../../components/ha-textfield"; @customElement("hui-input-list-editor") export class HuiInputListEditor extends LitElement { @@ -23,30 +23,31 @@ export class HuiInputListEditor extends LitElement { return html` ${this.value.map( (listEntry, index) => html` - Clear + > + + ` )} - + > `; } @@ -103,10 +104,12 @@ export class HuiInputListEditor extends LitElement { static get styles(): CSSResultGroup { return css` ha-icon-button { - --mdc-icon-button-size: 24px; - padding: 2px; + margin-right: -24px; color: var(--secondary-text-color); } + ha-textfield { + display: block; + } `; } } diff --git a/src/panels/lovelace/editor/config-elements/hui-map-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-map-card-editor.ts index 50c8fd65d3..ea0741ae33 100644 --- a/src/panels/lovelace/editor/config-elements/hui-map-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-map-card-editor.ts @@ -1,5 +1,4 @@ import "../../../../components/ha-form/ha-form"; -import "@polymer/paper-input/paper-input"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { @@ -24,7 +23,7 @@ import { EntityConfig } from "../../entity-rows/types"; import { LovelaceCardEditor } from "../../types"; import { processEditorEntities } from "../process-editor-entities"; import { entitiesConfigStruct } from "../structs/entities-struct"; -import { EditorTarget, EntitiesEditorEvent } from "../types"; +import { EntitiesEditorEvent } from "../types"; import { configElementStyle } from "./config-elements-style"; import { baseLovelaceCardConfig } from "../structs/base-card-struct"; import { HaFormSchema } from "../../../../components/ha-form/types"; @@ -127,10 +126,6 @@ export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor { if (!this._config || !this.hass) { return; } - const target = ev.target! as EditorTarget; - if (!target.configValue) { - return; - } const value = ev.detail.value; diff --git a/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts index 53288a843b..9b1f46f96b 100644 --- a/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts @@ -1,4 +1,3 @@ -import "@polymer/paper-input/paper-input"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { assert, object, optional, string, assign } from "superstruct"; From 64e1d160d1b9a505a658eb534f6b4de0c3bc9226 Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Mon, 7 Mar 2022 13:08:54 +0100 Subject: [PATCH 06/13] Correct media upload error + add file name (#11949) Co-authored-by: Bram Kragten --- src/data/image.ts | 2 +- src/data/media_source.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/image.ts b/src/data/image.ts index 497f2ffa3a..94198de6dc 100644 --- a/src/data/image.ts +++ b/src/data/image.ts @@ -29,7 +29,7 @@ export const createImage = async ( body: fd, }); if (resp.status === 413) { - throw new Error("Uploaded image is too large"); + throw new Error(`Uploaded image is too large (${file.name})`); } else if (resp.status !== 200) { throw new Error("Unknown error"); } diff --git a/src/data/media_source.ts b/src/data/media_source.ts index 61494ee3f8..a6e93d83cf 100644 --- a/src/data/media_source.ts +++ b/src/data/media_source.ts @@ -43,7 +43,7 @@ export const uploadLocalMedia = async ( } ); if (resp.status === 413) { - throw new Error("Uploaded image is too large"); + throw new Error(`Uploaded file is too large (${file.name})`); } else if (resp.status !== 200) { throw new Error("Unknown error"); } From ac7acc5802a83d18767d0ffaf9959fcfa1d43ce1 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 7 Mar 2022 14:25:38 +0100 Subject: [PATCH 07/13] Fix humidifier more info mode dropdown (#11964) --- .../controls/more-info-humidifier.ts | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/dialogs/more-info/controls/more-info-humidifier.ts b/src/dialogs/more-info/controls/more-info-humidifier.ts index bce976b45b..b5618e8619 100644 --- a/src/dialogs/more-info/controls/more-info-humidifier.ts +++ b/src/dialogs/more-info/controls/more-info-humidifier.ts @@ -1,3 +1,4 @@ +import "@material/mwc-list/mwc-list-item"; import { css, CSSResultGroup, @@ -12,6 +13,7 @@ import { fireEvent } from "../../../common/dom/fire_event"; import { stopPropagation } from "../../../common/dom/stop_propagation"; import { supportsFeature } from "../../../common/entity/supports-feature"; import { computeRTLDirection } from "../../../common/util/compute_rtl"; +import "../../../components/ha-select"; import "../../../components/ha-slider"; import "../../../components/ha-switch"; import { @@ -19,8 +21,6 @@ import { HUMIDIFIER_SUPPORT_MODES, } from "../../../data/humidifier"; import { HomeAssistant } from "../../../types"; -import "@material/mwc-list/mwc-list"; -import "@material/mwc-list/mwc-list-item"; class MoreInfoHumidifier extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -67,26 +67,24 @@ class MoreInfoHumidifier extends LitElement { ${supportModes ? html` -
- - ${stateObj.attributes.available_modes!.map( - (mode) => html` - - ${hass.localize( - `state_attributes.humidifier.mode.${mode}` - ) || mode} - - ` - )} - -
+ + ${stateObj.attributes.available_modes!.map( + (mode) => html` + + ${hass.localize( + `state_attributes.humidifier.mode.${mode}` + ) || mode} + + ` + )} + ` : ""}
From 0bbc0ebb3c92ed66e741388d164c0d34085f939e Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 7 Mar 2022 14:55:44 +0100 Subject: [PATCH 08/13] Make min width of select configurable (#11965) --- src/components/ha-select.ts | 3 +++ src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts | 1 + 2 files changed, 4 insertions(+) diff --git a/src/components/ha-select.ts b/src/components/ha-select.ts index 59269bde4a..b90133b8eb 100644 --- a/src/components/ha-select.ts +++ b/src/components/ha-select.ts @@ -44,6 +44,9 @@ export class HaSelect extends SelectBase { .mdc-select:not(.mdc-select--disabled) .mdc-select__icon { color: var(--secondary-text-color); } + .mdc-select__anchor { + width: var(--ha-select-min-width, 200px); + } `, ]; } diff --git a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts index 0b88452129..1db8a8c1b6 100644 --- a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts @@ -87,6 +87,7 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow { } ha-select { width: 100%; + --ha-select-min-width: 0; } `; From 552dbca2019d23b95d8096c4d8e796cff9e19bd9 Mon Sep 17 00:00:00 2001 From: Zack Barett Date: Mon, 7 Mar 2022 08:29:00 -0600 Subject: [PATCH 09/13] Fix for Statistics Editor (#11942) Co-authored-by: Bram Kragten --- .../config-elements/hui-statistics-graph-card-editor.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/panels/lovelace/editor/config-elements/hui-statistics-graph-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-statistics-graph-card-editor.ts index b68ecaebda..c695e56b54 100644 --- a/src/panels/lovelace/editor/config-elements/hui-statistics-graph-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-statistics-graph-card-editor.ts @@ -153,7 +153,7 @@ export class HuiStatisticsGraphCardEditor .pickedStatisticLabel=${`Statistic`} .value=${this._configEntities} .configValue=${"entities"} - @value-changed=${this._valueChanged} + @value-changed=${this._entitiesChanged} >
`; @@ -163,6 +163,12 @@ export class HuiStatisticsGraphCardEditor fireEvent(this, "config-changed", { config: ev.detail.value }); } + private _entitiesChanged(ev: CustomEvent): void { + fireEvent(this, "config-changed", { + config: { ...this._config!, entities: ev.detail.value }, + }); + } + private _computeLabelCallback = (schema: HaFormSchema) => this.hass!.localize( `ui.panel.lovelace.editor.card.generic.${schema.name}` From ec12282f8c4b6c4740d2196d68d2a922debab05e Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 7 Mar 2022 15:40:19 +0100 Subject: [PATCH 10/13] A11y expansion panel (#11967) --- src/components/ha-expansion-panel.ts | 58 +++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/src/components/ha-expansion-panel.ts b/src/components/ha-expansion-panel.ts index 705b5a6b81..b3dc414f1e 100644 --- a/src/components/ha-expansion-panel.ts +++ b/src/components/ha-expansion-panel.ts @@ -1,6 +1,13 @@ import { mdiChevronDown } from "@mdi/js"; -import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; -import { customElement, property, query } from "lit/decorators"; +import { + css, + CSSResultGroup, + html, + LitElement, + PropertyValues, + TemplateResult, +} from "lit"; +import { customElement, property, query, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { fireEvent } from "../common/dom/fire_event"; import { nextRender } from "../common/util/render-status"; @@ -16,11 +23,21 @@ class HaExpansionPanel extends LitElement { @property() secondary?: string; + @state() _showContent = this.expanded; + @query(".container") private _container!: HTMLDivElement; protected render(): TemplateResult { return html` -
+
${this.header} ${this.secondary} @@ -33,21 +50,37 @@ class HaExpansionPanel extends LitElement {
- + ${this._showContent ? html`` : ""}
`; } - private _handleTransitionEnd() { - this._container.style.removeProperty("height"); + protected willUpdate(changedProps: PropertyValues) { + if (changedProps.has("expanded") && this.expanded) { + this._showContent = this.expanded; + } } - private async _toggleContainer(): Promise { + private _handleTransitionEnd() { + this._container.style.removeProperty("height"); + this._showContent = this.expanded; + } + + private async _toggleContainer(ev): Promise { + if (ev.type === "keydown" && ev.key !== "Enter" && ev.key !== " ") { + return; + } + ev.preventDefault(); const newExpanded = !this.expanded; fireEvent(this, "expanded-will-change", { expanded: newExpanded }); if (newExpanded) { + this._showContent = true; // allow for dynamic content to be rendered await nextRender(); } @@ -80,17 +113,21 @@ class HaExpansionPanel extends LitElement { var(--divider-color, #e0e0e0) ); border-radius: var(--ha-card-border-radius, 4px); - padding: 0 8px; } - .summary { + #summary { display: flex; - padding: var(--expansion-panel-summary-padding, 0); + padding: var(--expansion-panel-summary-padding, 0 8px); min-height: 48px; align-items: center; cursor: pointer; overflow: hidden; font-weight: 500; + outline: none; + } + + #summary:focus { + background: var(--input-fill-color); } .summary-icon { @@ -103,6 +140,7 @@ class HaExpansionPanel extends LitElement { } .container { + padding: var(--expansion-panel-content-padding, 0 8px); overflow: hidden; transition: height 300ms cubic-bezier(0.4, 0, 0.2, 1); height: 0px; From 5bdecf57cffbac9f148fc65eaeb58a852d994d11 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 7 Mar 2022 15:42:40 +0100 Subject: [PATCH 11/13] Convert file upload to mdc (#11906) --- src/components/ha-file-upload.ts | 211 +++++++++++------- .../config/person/dialog-person-detail.ts | 3 + 2 files changed, 129 insertions(+), 85 deletions(-) diff --git a/src/components/ha-file-upload.ts b/src/components/ha-file-upload.ts index 31dd853e06..9c81a3f17a 100644 --- a/src/components/ha-file-upload.ts +++ b/src/components/ha-file-upload.ts @@ -1,6 +1,5 @@ +import { styles } from "@material/mwc-textfield/mwc-textfield.css"; import { mdiClose } from "@mdi/js"; -import "@polymer/iron-input/iron-input"; -import "@polymer/paper-input/paper-input-container"; import { css, html, LitElement, PropertyValues, TemplateResult } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; @@ -21,7 +20,7 @@ export class HaFileUpload extends LitElement { @property() public accept!: string; - @property() public icon!: string; + @property() public icon?: string; @property() public label!: string; @@ -39,15 +38,7 @@ export class HaFileUpload extends LitElement { protected firstUpdated(changedProperties: PropertyValues) { super.firstUpdated(changedProperties); if (this.autoOpenFileDialog) { - this._input?.click(); - } - } - - protected updated(changedProperties: PropertyValues) { - if (changedProperties.has("_drag") && !this.uploading) { - ( - this.shadowRoot!.querySelector("paper-input-container") as any - )._setFocused(this._drag); + this._openFilePicker(); } } @@ -60,51 +51,75 @@ export class HaFileUpload extends LitElement { active >` : html` - `} `; } + private _openFilePicker() { + this._input?.click(); + } + private _handleDrop(ev: DragEvent) { ev.preventDefault(); ev.stopPropagation(); @@ -137,40 +152,66 @@ export class HaFileUpload extends LitElement { } static get styles() { - return css` - paper-input-container { - position: relative; - padding: 8px; - margin: 0 -8px; - } - paper-input-container.dragged:before { - position: var(--layout-fit_-_position); - top: var(--layout-fit_-_top); - right: var(--layout-fit_-_right); - bottom: var(--layout-fit_-_bottom); - left: var(--layout-fit_-_left); - background: currentColor; - content: ""; - opacity: var(--dark-divider-opacity); - pointer-events: none; - border-radius: 4px; - } - input.file { - display: none; - } - img { - max-width: 125px; - max-height: 125px; - } - ha-icon-button { - --mdc-icon-button-size: 24px; - --mdc-icon-size: 20px; - } - ha-circular-progress { - display: block; - text-align-last: center; - } - `; + return [ + styles, + css` + :host { + display: block; + } + .mdc-text-field--filled { + height: auto; + padding-top: 16px; + cursor: pointer; + } + .mdc-text-field--filled.mdc-text-field--with-trailing-icon { + padding-top: 28px; + } + .mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__icon { + color: var(--secondary-text-color); + } + .mdc-text-field--filled.mdc-text-field--with-trailing-icon + .mdc-text-field__icon { + align-self: flex-end; + } + .mdc-text-field__icon--leading { + margin-bottom: 12px; + } + .mdc-text-field--filled .mdc-floating-label--float-above { + transform: scale(0.75); + top: 8px; + } + .dragged:before { + position: var(--layout-fit_-_position); + top: var(--layout-fit_-_top); + right: var(--layout-fit_-_right); + bottom: var(--layout-fit_-_bottom); + left: var(--layout-fit_-_left); + background: currentColor; + content: ""; + opacity: var(--dark-divider-opacity); + pointer-events: none; + border-radius: 4px; + } + .value { + width: 100%; + } + input.file { + display: none; + } + img { + max-width: 100%; + max-height: 125px; + } + ha-icon-button { + --mdc-icon-button-size: 24px; + --mdc-icon-size: 20px; + } + ha-circular-progress { + display: block; + text-align-last: center; + } + `, + ]; } } diff --git a/src/panels/config/person/dialog-person-detail.ts b/src/panels/config/person/dialog-person-detail.ts index 185056404f..9406d469f8 100644 --- a/src/panels/config/person/dialog-person-detail.ts +++ b/src/panels/config/person/dialog-person-detail.ts @@ -464,6 +464,9 @@ class DialogPersonDetail extends LitElement { ha-textfield { display: block; } + ha-picture-upload { + margin-top: 16px; + } ha-formfield { display: block; padding: 16px 0; From 96738350bbb5212a797e39eaaa2e7be11fcb91ff Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 7 Mar 2022 15:47:20 +0100 Subject: [PATCH 12/13] Add location selector, convert zone editor (#11902) --- gallery/src/pages/components/ha-form.ts | 5 + gallery/src/pages/components/ha-selector.ts | 5 + src/components/ha-form/ha-form-constant.ts | 4 +- src/components/ha-form/ha-form.ts | 4 +- src/components/ha-form/types.ts | 2 +- .../ha-selector/ha-selector-location.ts | 80 +++++ src/components/ha-selector/ha-selector.ts | 1 + src/data/selector.ts | 13 +- src/data/zone.ts | 6 +- src/panels/config/zone/dialog-zone-detail.ts | 310 +++++++----------- 10 files changed, 226 insertions(+), 204 deletions(-) create mode 100644 src/components/ha-selector/ha-selector-location.ts diff --git a/gallery/src/pages/components/ha-form.ts b/gallery/src/pages/components/ha-form.ts index b6ff6d1711..0722040cc0 100644 --- a/gallery/src/pages/components/ha-form.ts +++ b/gallery/src/pages/components/ha-form.ts @@ -38,6 +38,7 @@ const SCHEMAS: { select: "Select", icon: "Icon", media: "Media", + location: "Location", }, schema: [ { name: "addon", selector: { addon: {} } }, @@ -75,6 +76,10 @@ const SCHEMAS: { media: {}, }, }, + { + name: "location", + selector: { location: { radius: true, icon: "mdi:home" } }, + }, ], }, { diff --git a/gallery/src/pages/components/ha-selector.ts b/gallery/src/pages/components/ha-selector.ts index ea4a892015..600176d024 100644 --- a/gallery/src/pages/components/ha-selector.ts +++ b/gallery/src/pages/components/ha-selector.ts @@ -168,6 +168,11 @@ const SCHEMAS: { }, icon: { name: "Icon", selector: { icon: {} } }, media: { name: "Media", selector: { media: {} } }, + location: { name: "Location", selector: { location: {} } }, + location_radius: { + name: "Location with radius", + selector: { location: { radius: true, icon: "mdi:home" } }, + }, }, }, ]; diff --git a/src/components/ha-form/ha-form-constant.ts b/src/components/ha-form/ha-form-constant.ts index f20c057dfc..c1b6c67e9e 100644 --- a/src/components/ha-form/ha-form-constant.ts +++ b/src/components/ha-form/ha-form-constant.ts @@ -9,7 +9,9 @@ export class HaFormConstant extends LitElement implements HaFormElement { @property() public label!: string; protected render(): TemplateResult { - return html`${this.label}: ${this.schema.value}`; + return html`${this.label}${this.schema.value + ? `: ${this.schema.value}` + : ""}`; } static get styles(): CSSResultGroup { diff --git a/src/components/ha-form/ha-form.ts b/src/components/ha-form/ha-form.ts index c824d8fb89..e1e87d86f9 100644 --- a/src/components/ha-form/ha-form.ts +++ b/src/components/ha-form/ha-form.ts @@ -25,6 +25,8 @@ import { HomeAssistant } from "../../types"; const getValue = (obj, item) => obj ? (!item.name ? obj : obj[item.name]) : null; +const getError = (obj, item) => (obj && item.name ? obj[item.name] : null); + let selectorImported = false; @customElement("ha-form") @@ -84,7 +86,7 @@ export class HaForm extends LitElement implements HaFormElement { ` : ""} ${this.schema.map((item) => { - const error = getValue(this.error, item); + const error = getError(this.error, item); return html` ${error diff --git a/src/components/ha-form/types.ts b/src/components/ha-form/types.ts index fc45bc3ef1..2c3a9912d4 100644 --- a/src/components/ha-form/types.ts +++ b/src/components/ha-form/types.ts @@ -40,7 +40,7 @@ export interface HaFormSelector extends HaFormBaseSchema { export interface HaFormConstantSchema extends HaFormBaseSchema { type: "constant"; - value: string; + value?: string; } export interface HaFormIntegerSchema extends HaFormBaseSchema { diff --git a/src/components/ha-selector/ha-selector-location.ts b/src/components/ha-selector/ha-selector-location.ts new file mode 100644 index 0000000000..18372f525d --- /dev/null +++ b/src/components/ha-selector/ha-selector-location.ts @@ -0,0 +1,80 @@ +import { html, LitElement } from "lit"; +import { customElement, property } from "lit/decorators"; +import memoizeOne from "memoize-one"; +import { fireEvent } from "../../common/dom/fire_event"; +import type { + LocationSelector, + LocationSelectorValue, +} from "../../data/selector"; +import "../../panels/lovelace/components/hui-theme-select-editor"; +import type { HomeAssistant } from "../../types"; +import type { MarkerLocation } from "../map/ha-locations-editor"; +import "../map/ha-locations-editor"; + +@customElement("ha-selector-location") +export class HaLocationSelector extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: false }) public selector!: LocationSelector; + + @property() public value?: LocationSelectorValue; + + @property() public label?: string; + + @property({ type: Boolean, reflect: true }) public disabled = false; + + protected render() { + return html` + + `; + } + + private _location = memoizeOne( + ( + selector: LocationSelector, + value?: LocationSelectorValue + ): MarkerLocation[] => { + const computedStyles = getComputedStyle(this); + const zoneRadiusColor = selector.location.radius + ? computedStyles.getPropertyValue("--zone-radius-color") || + computedStyles.getPropertyValue("--accent-color") + : undefined; + return [ + { + id: "location", + latitude: value?.latitude || this.hass.config.latitude, + longitude: value?.longitude || this.hass.config.longitude, + radius: selector.location.radius ? value?.radius || 1000 : undefined, + radius_color: zoneRadiusColor, + icon: selector.location.icon, + location_editable: true, + radius_editable: true, + }, + ]; + } + ); + + private _locationChanged(ev: CustomEvent) { + const [latitude, longitude] = ev.detail.location; + fireEvent(this, "value-changed", { + value: { ...this.value, latitude, longitude }, + }); + } + + private _radiusChanged(ev: CustomEvent) { + const radius = ev.detail.radius; + fireEvent(this, "value-changed", { value: { ...this.value, radius } }); + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-selector-location": HaLocationSelector; + } +} diff --git a/src/components/ha-selector/ha-selector.ts b/src/components/ha-selector/ha-selector.ts index 5f6a31aebc..61b790cd98 100644 --- a/src/components/ha-selector/ha-selector.ts +++ b/src/components/ha-selector/ha-selector.ts @@ -20,6 +20,7 @@ import "./ha-selector-time"; import "./ha-selector-icon"; import "./ha-selector-media"; import "./ha-selector-theme"; +import "./ha-selector-location"; @customElement("ha-selector") export class HaSelector extends LitElement { diff --git a/src/data/selector.ts b/src/data/selector.ts index d8cb9a4e63..c8cc87b36e 100644 --- a/src/data/selector.ts +++ b/src/data/selector.ts @@ -15,7 +15,8 @@ export type Selector = | SelectSelector | IconSelector | MediaSelector - | ThemeSelector; + | ThemeSelector + | LocationSelector; export interface EntitySelector { entity: { @@ -164,6 +165,16 @@ export interface MediaSelector { media: {}; } +export interface LocationSelector { + location: { radius?: boolean; icon?: string }; +} + +export interface LocationSelectorValue { + latitude: number; + longitude: number; + radius?: number; +} + export interface MediaSelectorValue { entity_id?: string; media_content_id?: string; diff --git a/src/data/zone.ts b/src/data/zone.ts index a4e091c30e..52ea733317 100644 --- a/src/data/zone.ts +++ b/src/data/zone.ts @@ -12,12 +12,12 @@ export interface Zone { } export interface ZoneMutableParams { + name: string; icon?: string; latitude: number; longitude: number; - name: string; - passive: boolean; - radius: number; + passive?: boolean; + radius?: number; } export const fetchZones = (hass: HomeAssistant) => diff --git a/src/panels/config/zone/dialog-zone-detail.ts b/src/panels/config/zone/dialog-zone-detail.ts index 81c3e78807..07b9fcb4fa 100644 --- a/src/panels/config/zone/dialog-zone-detail.ts +++ b/src/panels/config/zone/dialog-zone-detail.ts @@ -1,17 +1,12 @@ import "@material/mwc-button"; -import "@polymer/paper-input/paper-input"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../common/dom/fire_event"; import { addDistanceToCoord } from "../../../common/location/add_distance_to_coord"; -import { computeRTLDirection } from "../../../common/util/compute_rtl"; import { createCloseHeading } from "../../../components/ha-dialog"; -import "../../../components/ha-formfield"; -import "../../../components/ha-icon-picker"; -import "../../../components/ha-switch"; -import "../../../components/map/ha-locations-editor"; -import type { MarkerLocation } from "../../../components/map/ha-locations-editor"; +import "../../../components/ha-form/ha-form"; +import { HaFormSchema } from "../../../components/ha-form/types"; import { getZoneEditorInitData, ZoneMutableParams } from "../../../data/zone"; import { haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; @@ -20,19 +15,9 @@ import { ZoneDetailDialogParams } from "./show-dialog-zone-detail"; class DialogZoneDetail extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @state() private _name!: string; + @state() private _error?: Record; - @state() private _icon!: string; - - @state() private _latitude!: number; - - @state() private _longitude!: number; - - @state() private _passive!: boolean; - - @state() private _radius!: number; - - @state() private _error?: string; + @state() private _data?: ZoneMutableParams; @state() private _params?: ZoneDetailDialogParams; @@ -42,13 +27,7 @@ class DialogZoneDetail extends LitElement { this._params = params; this._error = undefined; if (this._params.entry) { - this._name = this._params.entry.name || ""; - this._icon = this._params.entry.icon || ""; - this._latitude = this._params.entry.latitude || this.hass.config.latitude; - this._longitude = - this._params.entry.longitude || this.hass.config.longitude; - this._passive = this._params.entry.passive || false; - this._radius = this._params.entry.radius || 100; + this._data = this._params.entry; } else { const initConfig = getZoneEditorInitData(); let movedHomeLocation; @@ -59,30 +38,34 @@ class DialogZoneDetail extends LitElement { Math.random() * 500 * (Math.random() < 0.5 ? -1 : 1) ); } - this._latitude = initConfig?.latitude || movedHomeLocation[0]; - this._longitude = initConfig?.longitude || movedHomeLocation[1]; - this._name = initConfig?.name || ""; - this._icon = initConfig?.icon || "mdi:map-marker"; - - this._passive = false; - this._radius = 100; + this._data = { + latitude: initConfig?.latitude || movedHomeLocation[0], + longitude: initConfig?.longitude || movedHomeLocation[1], + name: initConfig?.name || "", + icon: initConfig?.icon || "mdi:map-marker", + passive: false, + radius: 100, + }; } } public closeDialog(): void { this._params = undefined; + this._data = undefined; fireEvent(this, "dialog-closed", { dialog: this.localName }); } protected render(): TemplateResult { - if (!this._params) { + if (!this._params || !this._data) { return html``; } - const nameInvalid = this._name.trim() === ""; - const iconInvalid = Boolean(this._icon && !this._icon.trim().includes(":")); - const latInvalid = String(this._latitude) === ""; - const lngInvalid = String(this._longitude) === ""; - const radiusInvalid = String(this._radius) === ""; + const nameInvalid = this._data.name.trim() === ""; + const iconInvalid = Boolean( + this._data.icon && !this._data.icon.trim().includes(":") + ); + const latInvalid = String(this._data.latitude) === ""; + const lngInvalid = String(this._data.longitude) === ""; + const radiusInvalid = String(this._data.radius) === ""; const valid = !nameInvalid && @@ -105,96 +88,15 @@ class DialogZoneDetail extends LitElement { )} >
- ${this._error ? html`
${this._error}
` : ""} -
- - - -
- - -
- -

- ${this.hass!.localize("ui.panel.config.zone.detail.passive_note")} -

- - - -
+
${this._params.entry ? html` @@ -221,74 +123,94 @@ class DialogZoneDetail extends LitElement { `; } - private _location = memoizeOne( - ( - lat: number, - lng: number, - radius: number, - passive: boolean, - icon: string - ): MarkerLocation[] => { - const computedStyles = getComputedStyle(this); - const zoneRadiusColor = computedStyles.getPropertyValue("--accent-color"); - const passiveRadiusColor = computedStyles.getPropertyValue( - "--secondary-text-color" - ); - return [ + private _schema = memoizeOne((icon?: string): HaFormSchema[] => [ + { + name: "name", + required: true, + selector: { + text: {}, + }, + }, + { + name: "icon", + required: false, + selector: { + icon: {}, + }, + }, + { + name: "location", + required: true, + selector: { location: { radius: true, icon } }, + }, + { + name: "", + type: "grid", + schema: [ { - id: "location", - latitude: Number(lat), - longitude: Number(lng), - radius, - radius_color: passive ? passiveRadiusColor : zoneRadiusColor, - icon, - location_editable: true, - radius_editable: true, + name: "latitude", + required: true, + selector: { text: {} }, }, - ]; - } - ); + { + name: "longitude", + required: true, - private _locationChanged(ev: CustomEvent) { - [this._latitude, this._longitude] = ev.detail.location; - } + selector: { text: {} }, + }, + ], + }, + { name: "passive_note", type: "constant" }, + { name: "passive", selector: { boolean: {} } }, + { + name: "radius", + required: false, + selector: { number: { min: 0, max: 999999, mode: "box" } }, + }, + ]); - private _radiusChanged(ev: CustomEvent) { - this._radius = ev.detail.radius; - } - - private _passiveChanged(ev) { - this._passive = ev.target.checked; - } + private _formData = memoizeOne((data: ZoneMutableParams) => ({ + ...data, + location: { + latitude: data.latitude, + longitude: data.longitude, + radius: data.radius, + }, + })); private _valueChanged(ev: CustomEvent) { - const configValue = (ev.target as any).configValue; - this._error = undefined; - this[`_${configValue}`] = ev.detail.value; + const value = ev.detail.value; + if ( + value.location.latitude !== this._data!.latitude || + value.location.longitude !== this._data!.longitude || + value.location.radius !== this._data!.radius + ) { + value.latitude = value.location.latitude; + value.longitude = value.location.longitude; + value.radius = Math.round(value.location.radius); + } + delete value.location; + if (!value.icon) { + delete value.icon; + } + this._data = value; } + private _computeLabel = (entry: HaFormSchema): string => + this.hass.localize(`ui.panel.config.zone.detail.${entry.name}`); + private async _updateEntry() { this._submitting = true; try { - const values: ZoneMutableParams = { - name: this._name.trim(), - latitude: this._latitude, - longitude: this._longitude, - passive: this._passive, - radius: this._radius, - }; - if (this._icon) { - values.icon = this._icon.trim(); - } if (this._params!.entry) { - await this._params!.updateEntry!(values); + await this._params!.updateEntry!(this._data!); } else { - await this._params!.createEntry(values); + await this._params!.createEntry(this._data!); } - this._params = undefined; + this.closeDialog(); } catch (err: any) { - this._error = err ? err.message : "Unknown error"; + this._error = { base: err ? err.message : "Unknown error" }; } finally { this._submitting = false; } @@ -309,24 +231,18 @@ class DialogZoneDetail extends LitElement { return [ haStyleDialog, css` - .location { - display: flex; + ha-dialog { + --mdc-dialog-min-width: 600px; } - .location > * { - flex-grow: 1; - min-width: 0; + @media all and (max-width: 450px), all and (max-height: 500px) { + ha-dialog { + --mdc-dialog-min-width: calc( + 100vw - env(safe-area-inset-right) - env(safe-area-inset-left) + ); + } } - .location > *:first-child { - margin-right: 4px; - } - .location > *:last-child { - margin-left: 4px; - } - ha-locations-editor { - margin-top: 16px; - } - a { - color: var(--primary-color); + ha-form.passive { + --zone-radius-color: var(--secondary-text-color); } `, ]; From 1dd5214b4255f0d063a91acfdc3191a81520d34a Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 7 Mar 2022 16:51:41 +0100 Subject: [PATCH 13/13] Bumped version to 20220301.1 --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 13b918a742..3b273584c0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = home-assistant-frontend -version = 20220301.0 +version = 20220301.1 author = The Home Assistant Authors author_email = hello@home-assistant.io license = Apache-2.0