mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-26 02:36:37 +00:00
Z-Wave: Prevent closing the Add Device dialog when user input is required (#20999)
* prevent closing the Z-Wave Add node dialog when user input is required * ask user for confirmation before leaving page during bootstrapping * fix: no non-null assertion
This commit is contained in:
parent
c7b4e8f37c
commit
9a3f7df25e
@ -3,6 +3,7 @@ import { mdiAlertCircle, mdiCheckCircle, mdiQrcodeScan } from "@mdi/js";
|
|||||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
|
import { ifDefined } from "lit/directives/if-defined";
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
import "../../../../../components/ha-alert";
|
import "../../../../../components/ha-alert";
|
||||||
import type { HaCheckbox } from "../../../../../components/ha-checkbox";
|
import type { HaCheckbox } from "../../../../../components/ha-checkbox";
|
||||||
@ -60,7 +61,8 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
| "finished"
|
| "finished"
|
||||||
| "provisioned"
|
| "provisioned"
|
||||||
| "validate_dsk_enter_pin"
|
| "validate_dsk_enter_pin"
|
||||||
| "grant_security_classes";
|
| "grant_security_classes"
|
||||||
|
| "waiting_for_device";
|
||||||
|
|
||||||
@state() private _device?: ZWaveJSAddNodeDevice;
|
@state() private _device?: ZWaveJSAddNodeDevice;
|
||||||
|
|
||||||
@ -86,6 +88,11 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
|
|
||||||
private _qrProcessing = false;
|
private _qrProcessing = false;
|
||||||
|
|
||||||
|
public connectedCallback(): void {
|
||||||
|
super.connectedCallback();
|
||||||
|
window.addEventListener("beforeunload", this._onBeforeUnload);
|
||||||
|
}
|
||||||
|
|
||||||
public disconnectedCallback(): void {
|
public disconnectedCallback(): void {
|
||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
this._unsubscribe();
|
this._unsubscribe();
|
||||||
@ -106,14 +113,22 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
return nothing;
|
return nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent accidentally closing the dialog in certain stages
|
||||||
|
const preventClose = this._shouldPreventClose();
|
||||||
|
|
||||||
|
const heading = this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.add_node.title"
|
||||||
|
);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-dialog
|
<ha-dialog
|
||||||
open
|
open
|
||||||
@closed=${this.closeDialog}
|
@closed=${this.closeDialog}
|
||||||
.heading=${createCloseHeading(
|
.heading=${preventClose
|
||||||
this.hass,
|
? heading
|
||||||
this.hass.localize("ui.panel.config.zwave_js.add_node.title")
|
: createCloseHeading(this.hass, heading)}
|
||||||
)}
|
scrimClickAction=${ifDefined(preventClose ? "" : undefined)}
|
||||||
|
escapeKeyAction=${ifDefined(preventClose ? "" : undefined)}
|
||||||
>
|
>
|
||||||
${this._status === "loading"
|
${this._status === "loading"
|
||||||
? html`<div style="display: flex; justify-content: center;">
|
? html`<div style="display: flex; justify-content: center;">
|
||||||
@ -122,6 +137,15 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
indeterminate
|
indeterminate
|
||||||
></ha-circular-progress>
|
></ha-circular-progress>
|
||||||
</div>`
|
</div>`
|
||||||
|
: this._status === "waiting_for_device"
|
||||||
|
? html`<div class="flex-container">
|
||||||
|
<ha-circular-progress indeterminate></ha-circular-progress>
|
||||||
|
<p>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.zwave_js.add_node.waiting_for_device"
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>`
|
||||||
: this._status === "choose_strategy"
|
: this._status === "choose_strategy"
|
||||||
? html`<h3>Choose strategy</h3>
|
? html`<h3>Choose strategy</h3>
|
||||||
<div class="flex-column">
|
<div class="flex-column">
|
||||||
@ -129,8 +153,8 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
.label=${html`<b>Secure if possible</b>
|
.label=${html`<b>Secure if possible</b>
|
||||||
<div class="secondary">
|
<div class="secondary">
|
||||||
Requires user interaction during inclusion. Fast and
|
Requires user interaction during inclusion. Fast and
|
||||||
secure with S2 when supported. Fallback to legacy S0 or
|
secure with S2 when supported. Fallback to legacy S0
|
||||||
no encryption when necessary.
|
or no encryption when necessary.
|
||||||
</div>`}
|
</div>`}
|
||||||
>
|
>
|
||||||
<ha-radio
|
<ha-radio
|
||||||
@ -146,8 +170,8 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
<ha-formfield
|
<ha-formfield
|
||||||
.label=${html`<b>Legacy Secure</b>
|
.label=${html`<b>Legacy Secure</b>
|
||||||
<div class="secondary">
|
<div class="secondary">
|
||||||
Uses the older S0 security that is secure, but slow due
|
Uses the older S0 security that is secure, but slow
|
||||||
to a lot of overhead. Allows securely including S2
|
due to a lot of overhead. Allows securely including S2
|
||||||
capable devices which fail to be included with S2.
|
capable devices which fail to be included with S2.
|
||||||
</div>`}
|
</div>`}
|
||||||
>
|
>
|
||||||
@ -190,7 +214,10 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
.localize=${this.hass.localize}
|
.localize=${this.hass.localize}
|
||||||
@qr-code-scanned=${this._qrCodeScanned}
|
@qr-code-scanned=${this._qrCodeScanned}
|
||||||
></ha-qr-scanner>
|
></ha-qr-scanner>
|
||||||
<mwc-button slot="secondaryAction" @click=${this._startOver}>
|
<mwc-button
|
||||||
|
slot="secondaryAction"
|
||||||
|
@click=${this._startOver}
|
||||||
|
>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.zwave_js.common.back"
|
"ui.panel.config.zwave_js.common.back"
|
||||||
)}
|
)}
|
||||||
@ -228,7 +255,8 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
: this._status === "grant_security_classes"
|
: this._status === "grant_security_classes"
|
||||||
? html`
|
? html`
|
||||||
<h3>
|
<h3>
|
||||||
The device has requested the following security classes:
|
The device has requested the following security
|
||||||
|
classes:
|
||||||
</h3>
|
</h3>
|
||||||
${this._error
|
${this._error
|
||||||
? html`<ha-alert alert-type="error"
|
? html`<ha-alert alert-type="error"
|
||||||
@ -471,7 +499,7 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
: ""}
|
: ""}
|
||||||
<a
|
<a
|
||||||
href=${`/config/devices/device/${
|
href=${`/config/devices/device/${
|
||||||
this._device!.id
|
this._device?.id
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<mwc-button>
|
<mwc-button>
|
||||||
@ -529,6 +557,15 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _shouldPreventClose(): boolean {
|
||||||
|
return (
|
||||||
|
this._status === "started_specific" ||
|
||||||
|
this._status === "validate_dsk_enter_pin" ||
|
||||||
|
this._status === "grant_security_classes" ||
|
||||||
|
this._status === "waiting_for_device"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private _chooseInclusionStrategy(): void {
|
private _chooseInclusionStrategy(): void {
|
||||||
this._unsubscribe();
|
this._unsubscribe();
|
||||||
this._status = "choose_strategy";
|
this._status = "choose_strategy";
|
||||||
@ -639,7 +676,7 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _validateDskAndEnterPin(): Promise<void> {
|
private async _validateDskAndEnterPin(): Promise<void> {
|
||||||
this._status = "loading";
|
this._status = "waiting_for_device";
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
try {
|
try {
|
||||||
await zwaveValidateDskAndEnterPin(
|
await zwaveValidateDskAndEnterPin(
|
||||||
@ -656,7 +693,7 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _grantSecurityClasses(): Promise<void> {
|
private async _grantSecurityClasses(): Promise<void> {
|
||||||
this._status = "loading";
|
this._status = "waiting_for_device";
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
try {
|
try {
|
||||||
await zwaveGrantSecurityClasses(
|
await zwaveGrantSecurityClasses(
|
||||||
@ -719,6 +756,12 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
this._addNodeTimeoutHandle = undefined;
|
this._addNodeTimeoutHandle = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message.event === "node found") {
|
||||||
|
// The user may have to enter a PIN. Until then prevent accidentally
|
||||||
|
// closing the dialog
|
||||||
|
this._status = "waiting_for_device";
|
||||||
|
}
|
||||||
|
|
||||||
if (message.event === "validate dsk and enter pin") {
|
if (message.event === "validate dsk and enter pin") {
|
||||||
this._status = "validate_dsk_enter_pin";
|
this._status = "validate_dsk_enter_pin";
|
||||||
this._dsk = message.dsk;
|
this._dsk = message.dsk;
|
||||||
@ -775,6 +818,13 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
}, 90000);
|
}, 90000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _onBeforeUnload = (event: BeforeUnloadEvent) => {
|
||||||
|
if (this._shouldPreventClose()) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
event.returnValue = true;
|
||||||
|
};
|
||||||
|
|
||||||
private _unsubscribe(): void {
|
private _unsubscribe(): void {
|
||||||
if (this._subscribed) {
|
if (this._subscribed) {
|
||||||
this._subscribed.then((unsub) => unsub());
|
this._subscribed.then((unsub) => unsub());
|
||||||
@ -791,6 +841,7 @@ class DialogZWaveJSAddNode extends LitElement {
|
|||||||
clearTimeout(this._addNodeTimeoutHandle);
|
clearTimeout(this._addNodeTimeoutHandle);
|
||||||
}
|
}
|
||||||
this._addNodeTimeoutHandle = undefined;
|
this._addNodeTimeoutHandle = undefined;
|
||||||
|
window.removeEventListener("beforeunload", this._onBeforeUnload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeDialog(): void {
|
public closeDialog(): void {
|
||||||
|
@ -4863,7 +4863,8 @@
|
|||||||
"provisioning_finished": "The device has been added. Once you power it on, it will become available.",
|
"provisioning_finished": "The device has been added. Once you power it on, it will become available.",
|
||||||
"view_device": "View Device",
|
"view_device": "View Device",
|
||||||
"interview_started": "The device is being interviewed. This may take some time.",
|
"interview_started": "The device is being interviewed. This may take some time.",
|
||||||
"interview_failed": "The device interview failed. Additional information may be available in the logs."
|
"interview_failed": "The device interview failed. Additional information may be available in the logs.",
|
||||||
|
"waiting_for_device": "Communicating with the device. Please wait."
|
||||||
},
|
},
|
||||||
"provisioned": {
|
"provisioned": {
|
||||||
"dsk": "DSK",
|
"dsk": "DSK",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user