mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +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 { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||
import "../../../../../components/ha-alert";
|
||||
import type { HaCheckbox } from "../../../../../components/ha-checkbox";
|
||||
@ -60,7 +61,8 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
| "finished"
|
||||
| "provisioned"
|
||||
| "validate_dsk_enter_pin"
|
||||
| "grant_security_classes";
|
||||
| "grant_security_classes"
|
||||
| "waiting_for_device";
|
||||
|
||||
@state() private _device?: ZWaveJSAddNodeDevice;
|
||||
|
||||
@ -86,6 +88,11 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
|
||||
private _qrProcessing = false;
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
window.addEventListener("beforeunload", this._onBeforeUnload);
|
||||
}
|
||||
|
||||
public disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
this._unsubscribe();
|
||||
@ -106,14 +113,22 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
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`
|
||||
<ha-dialog
|
||||
open
|
||||
@closed=${this.closeDialog}
|
||||
.heading=${createCloseHeading(
|
||||
this.hass,
|
||||
this.hass.localize("ui.panel.config.zwave_js.add_node.title")
|
||||
)}
|
||||
.heading=${preventClose
|
||||
? heading
|
||||
: createCloseHeading(this.hass, heading)}
|
||||
scrimClickAction=${ifDefined(preventClose ? "" : undefined)}
|
||||
escapeKeyAction=${ifDefined(preventClose ? "" : undefined)}
|
||||
>
|
||||
${this._status === "loading"
|
||||
? html`<div style="display: flex; justify-content: center;">
|
||||
@ -122,81 +137,93 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
indeterminate
|
||||
></ha-circular-progress>
|
||||
</div>`
|
||||
: this._status === "choose_strategy"
|
||||
? html`<h3>Choose strategy</h3>
|
||||
<div class="flex-column">
|
||||
<ha-formfield
|
||||
.label=${html`<b>Secure if possible</b>
|
||||
<div class="secondary">
|
||||
Requires user interaction during inclusion. Fast and
|
||||
secure with S2 when supported. Fallback to legacy S0 or
|
||||
no encryption when necessary.
|
||||
</div>`}
|
||||
>
|
||||
<ha-radio
|
||||
name="strategy"
|
||||
@change=${this._handleStrategyChange}
|
||||
.value=${InclusionStrategy.Default}
|
||||
.checked=${this._inclusionStrategy ===
|
||||
InclusionStrategy.Default ||
|
||||
this._inclusionStrategy === undefined}
|
||||
: 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"
|
||||
? html`<h3>Choose strategy</h3>
|
||||
<div class="flex-column">
|
||||
<ha-formfield
|
||||
.label=${html`<b>Secure if possible</b>
|
||||
<div class="secondary">
|
||||
Requires user interaction during inclusion. Fast and
|
||||
secure with S2 when supported. Fallback to legacy S0
|
||||
or no encryption when necessary.
|
||||
</div>`}
|
||||
>
|
||||
</ha-radio>
|
||||
</ha-formfield>
|
||||
<ha-formfield
|
||||
.label=${html`<b>Legacy Secure</b>
|
||||
<div class="secondary">
|
||||
Uses the older S0 security that is secure, but slow due
|
||||
to a lot of overhead. Allows securely including S2
|
||||
capable devices which fail to be included with S2.
|
||||
</div>`}
|
||||
>
|
||||
<ha-radio
|
||||
name="strategy"
|
||||
@change=${this._handleStrategyChange}
|
||||
.value=${InclusionStrategy.Security_S0}
|
||||
.checked=${this._inclusionStrategy ===
|
||||
InclusionStrategy.Security_S0}
|
||||
<ha-radio
|
||||
name="strategy"
|
||||
@change=${this._handleStrategyChange}
|
||||
.value=${InclusionStrategy.Default}
|
||||
.checked=${this._inclusionStrategy ===
|
||||
InclusionStrategy.Default ||
|
||||
this._inclusionStrategy === undefined}
|
||||
>
|
||||
</ha-radio>
|
||||
</ha-formfield>
|
||||
<ha-formfield
|
||||
.label=${html`<b>Legacy Secure</b>
|
||||
<div class="secondary">
|
||||
Uses the older S0 security that is secure, but slow
|
||||
due to a lot of overhead. Allows securely including S2
|
||||
capable devices which fail to be included with S2.
|
||||
</div>`}
|
||||
>
|
||||
</ha-radio>
|
||||
</ha-formfield>
|
||||
<ha-formfield
|
||||
.label=${html`<b>Insecure</b>
|
||||
<div class="secondary">Do not use encryption.</div>`}
|
||||
>
|
||||
<ha-radio
|
||||
name="strategy"
|
||||
@change=${this._handleStrategyChange}
|
||||
.value=${InclusionStrategy.Insecure}
|
||||
.checked=${this._inclusionStrategy ===
|
||||
InclusionStrategy.Insecure}
|
||||
<ha-radio
|
||||
name="strategy"
|
||||
@change=${this._handleStrategyChange}
|
||||
.value=${InclusionStrategy.Security_S0}
|
||||
.checked=${this._inclusionStrategy ===
|
||||
InclusionStrategy.Security_S0}
|
||||
>
|
||||
</ha-radio>
|
||||
</ha-formfield>
|
||||
<ha-formfield
|
||||
.label=${html`<b>Insecure</b>
|
||||
<div class="secondary">Do not use encryption.</div>`}
|
||||
>
|
||||
</ha-radio>
|
||||
</ha-formfield>
|
||||
</div>
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
@click=${this._startManualInclusion}
|
||||
>
|
||||
Search device
|
||||
</mwc-button>`
|
||||
: this._status === "qr_scan"
|
||||
? html`${this._error
|
||||
? html`<ha-alert alert-type="error"
|
||||
>${this._error}</ha-alert
|
||||
>`
|
||||
: ""}
|
||||
<ha-qr-scanner
|
||||
.localize=${this.hass.localize}
|
||||
@qr-code-scanned=${this._qrCodeScanned}
|
||||
></ha-qr-scanner>
|
||||
<mwc-button slot="secondaryAction" @click=${this._startOver}>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.common.back"
|
||||
)}
|
||||
<ha-radio
|
||||
name="strategy"
|
||||
@change=${this._handleStrategyChange}
|
||||
.value=${InclusionStrategy.Insecure}
|
||||
.checked=${this._inclusionStrategy ===
|
||||
InclusionStrategy.Insecure}
|
||||
>
|
||||
</ha-radio>
|
||||
</ha-formfield>
|
||||
</div>
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
@click=${this._startManualInclusion}
|
||||
>
|
||||
Search device
|
||||
</mwc-button>`
|
||||
: this._status === "validate_dsk_enter_pin"
|
||||
? html`
|
||||
: this._status === "qr_scan"
|
||||
? html`${this._error
|
||||
? html`<ha-alert alert-type="error"
|
||||
>${this._error}</ha-alert
|
||||
>`
|
||||
: ""}
|
||||
<ha-qr-scanner
|
||||
.localize=${this.hass.localize}
|
||||
@qr-code-scanned=${this._qrCodeScanned}
|
||||
></ha-qr-scanner>
|
||||
<mwc-button
|
||||
slot="secondaryAction"
|
||||
@click=${this._startOver}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.common.back"
|
||||
)}
|
||||
</mwc-button>`
|
||||
: this._status === "validate_dsk_enter_pin"
|
||||
? html`
|
||||
<p>
|
||||
Please enter the 5-digit PIN for your device and verify that
|
||||
the rest of the device-specific key matches the one that can
|
||||
@ -225,198 +252,160 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
</mwc-button>
|
||||
</div>
|
||||
`
|
||||
: this._status === "grant_security_classes"
|
||||
? html`
|
||||
<h3>
|
||||
The device has requested the following security classes:
|
||||
</h3>
|
||||
${this._error
|
||||
? html`<ha-alert alert-type="error"
|
||||
>${this._error}</ha-alert
|
||||
>`
|
||||
: ""}
|
||||
<div class="flex-column">
|
||||
${this._requestedGrant?.securityClasses
|
||||
.sort((a, b) => {
|
||||
// Put highest security classes at the top, S0 at the bottom
|
||||
if (a === SecurityClass.S0_Legacy) return 1;
|
||||
if (b === SecurityClass.S0_Legacy) return -1;
|
||||
return b - a;
|
||||
})
|
||||
.map(
|
||||
(securityClass) =>
|
||||
html`<ha-formfield
|
||||
.label=${html`<b
|
||||
>${this.hass.localize(
|
||||
`ui.panel.config.zwave_js.security_classes.${SecurityClass[securityClass]}.title`
|
||||
)}</b
|
||||
>
|
||||
<div class="secondary">
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.zwave_js.security_classes.${SecurityClass[securityClass]}.description`
|
||||
)}
|
||||
</div>`}
|
||||
>
|
||||
<ha-checkbox
|
||||
@change=${this._handleSecurityClassChange}
|
||||
.value=${securityClass}
|
||||
.checked=${this._securityClasses.includes(
|
||||
securityClass
|
||||
)}
|
||||
>
|
||||
</ha-checkbox>
|
||||
</ha-formfield>`
|
||||
)}
|
||||
</div>
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
.disabled=${!this._securityClasses.length}
|
||||
@click=${this._grantSecurityClasses}
|
||||
>
|
||||
Submit
|
||||
</mwc-button>
|
||||
`
|
||||
: this._status === "timed_out"
|
||||
: this._status === "grant_security_classes"
|
||||
? html`
|
||||
<h3>Timed out!</h3>
|
||||
<p>
|
||||
We have not found any device in inclusion mode. Make
|
||||
sure the device is active and in inclusion mode.
|
||||
</p>
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
@click=${this._startOver}
|
||||
>
|
||||
Retry
|
||||
</mwc-button>
|
||||
`
|
||||
: this._status === "started_specific"
|
||||
? html`<h3>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.searching_device"
|
||||
)}
|
||||
</h3>
|
||||
<ha-circular-progress
|
||||
indeterminate
|
||||
></ha-circular-progress>
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.follow_device_instructions"
|
||||
)}
|
||||
</p>`
|
||||
: this._status === "started"
|
||||
? html`
|
||||
<div class="select-inclusion">
|
||||
<div class="outline">
|
||||
<h2>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.searching_device"
|
||||
)}
|
||||
</h2>
|
||||
<ha-circular-progress
|
||||
indeterminate
|
||||
></ha-circular-progress>
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.follow_device_instructions"
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
<button
|
||||
class="link"
|
||||
@click=${this._chooseInclusionStrategy}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.choose_inclusion_strategy"
|
||||
)}
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
${this._supportsSmartStart
|
||||
? html` <div class="outline">
|
||||
<h2>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.qr_code"
|
||||
)}
|
||||
</h2>
|
||||
<ha-svg-icon
|
||||
.path=${mdiQrcodeScan}
|
||||
></ha-svg-icon>
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.qr_code_paragraph"
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
<mwc-button @click=${this._scanQRCode}>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.scan_qr_code"
|
||||
)}
|
||||
</mwc-button>
|
||||
</p>
|
||||
</div>`
|
||||
: ""}
|
||||
</div>
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
@click=${this.closeDialog}
|
||||
>
|
||||
${this.hass.localize("ui.common.cancel")}
|
||||
</mwc-button>
|
||||
`
|
||||
: this._status === "interviewing"
|
||||
? html`
|
||||
<div class="flex-container">
|
||||
<ha-circular-progress
|
||||
indeterminate
|
||||
></ha-circular-progress>
|
||||
<div class="status">
|
||||
<p>
|
||||
<b
|
||||
<h3>
|
||||
The device has requested the following security
|
||||
classes:
|
||||
</h3>
|
||||
${this._error
|
||||
? html`<ha-alert alert-type="error"
|
||||
>${this._error}</ha-alert
|
||||
>`
|
||||
: ""}
|
||||
<div class="flex-column">
|
||||
${this._requestedGrant?.securityClasses
|
||||
.sort((a, b) => {
|
||||
// Put highest security classes at the top, S0 at the bottom
|
||||
if (a === SecurityClass.S0_Legacy) return 1;
|
||||
if (b === SecurityClass.S0_Legacy) return -1;
|
||||
return b - a;
|
||||
})
|
||||
.map(
|
||||
(securityClass) =>
|
||||
html`<ha-formfield
|
||||
.label=${html`<b
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.interview_started"
|
||||
`ui.panel.config.zwave_js.security_classes.${SecurityClass[securityClass]}.title`
|
||||
)}</b
|
||||
>
|
||||
<div class="secondary">
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.zwave_js.security_classes.${SecurityClass[securityClass]}.description`
|
||||
)}
|
||||
</div>`}
|
||||
>
|
||||
<ha-checkbox
|
||||
@change=${this._handleSecurityClassChange}
|
||||
.value=${securityClass}
|
||||
.checked=${this._securityClasses.includes(
|
||||
securityClass
|
||||
)}
|
||||
>
|
||||
</ha-checkbox>
|
||||
</ha-formfield>`
|
||||
)}
|
||||
</div>
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
.disabled=${!this._securityClasses.length}
|
||||
@click=${this._grantSecurityClasses}
|
||||
>
|
||||
Submit
|
||||
</mwc-button>
|
||||
`
|
||||
: this._status === "timed_out"
|
||||
? html`
|
||||
<h3>Timed out!</h3>
|
||||
<p>
|
||||
We have not found any device in inclusion mode. Make
|
||||
sure the device is active and in inclusion mode.
|
||||
</p>
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
@click=${this._startOver}
|
||||
>
|
||||
Retry
|
||||
</mwc-button>
|
||||
`
|
||||
: this._status === "started_specific"
|
||||
? html`<h3>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.searching_device"
|
||||
)}
|
||||
</h3>
|
||||
<ha-circular-progress
|
||||
indeterminate
|
||||
></ha-circular-progress>
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.follow_device_instructions"
|
||||
)}
|
||||
</p>`
|
||||
: this._status === "started"
|
||||
? html`
|
||||
<div class="select-inclusion">
|
||||
<div class="outline">
|
||||
<h2>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.searching_device"
|
||||
)}
|
||||
</h2>
|
||||
<ha-circular-progress
|
||||
indeterminate
|
||||
></ha-circular-progress>
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.follow_device_instructions"
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
<button
|
||||
class="link"
|
||||
@click=${this._chooseInclusionStrategy}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.choose_inclusion_strategy"
|
||||
)}
|
||||
</button>
|
||||
</p>
|
||||
${this._stages
|
||||
? html` <div class="stages">
|
||||
${this._stages.map(
|
||||
(stage) => html`
|
||||
<span class="stage">
|
||||
<ha-svg-icon
|
||||
.path=${mdiCheckCircle}
|
||||
class="success"
|
||||
></ha-svg-icon>
|
||||
${stage}
|
||||
</span>
|
||||
`
|
||||
)}
|
||||
</div>`
|
||||
: ""}
|
||||
</div>
|
||||
${this._supportsSmartStart
|
||||
? html` <div class="outline">
|
||||
<h2>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.qr_code"
|
||||
)}
|
||||
</h2>
|
||||
<ha-svg-icon
|
||||
.path=${mdiQrcodeScan}
|
||||
></ha-svg-icon>
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.qr_code_paragraph"
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
<mwc-button @click=${this._scanQRCode}>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.scan_qr_code"
|
||||
)}
|
||||
</mwc-button>
|
||||
</p>
|
||||
</div>`
|
||||
: ""}
|
||||
</div>
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
@click=${this.closeDialog}
|
||||
>
|
||||
${this.hass.localize("ui.common.close")}
|
||||
${this.hass.localize("ui.common.cancel")}
|
||||
</mwc-button>
|
||||
`
|
||||
: this._status === "failed"
|
||||
: this._status === "interviewing"
|
||||
? html`
|
||||
<div class="flex-container">
|
||||
<ha-circular-progress
|
||||
indeterminate
|
||||
></ha-circular-progress>
|
||||
<div class="status">
|
||||
<ha-alert
|
||||
alert-type="error"
|
||||
.title=${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.inclusion_failed"
|
||||
)}
|
||||
>
|
||||
${this._error ||
|
||||
this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.check_logs"
|
||||
)}
|
||||
</ha-alert>
|
||||
<p>
|
||||
<b
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.interview_started"
|
||||
)}</b
|
||||
>
|
||||
</p>
|
||||
${this._stages
|
||||
? html` <div class="stages">
|
||||
${this._stages.map(
|
||||
@ -441,45 +430,21 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
${this.hass.localize("ui.common.close")}
|
||||
</mwc-button>
|
||||
`
|
||||
: this._status === "finished"
|
||||
: this._status === "failed"
|
||||
? html`
|
||||
<div class="flex-container">
|
||||
<ha-svg-icon
|
||||
.path=${this._lowSecurity
|
||||
? mdiAlertCircle
|
||||
: mdiCheckCircle}
|
||||
class=${this._lowSecurity
|
||||
? "warning"
|
||||
: "success"}
|
||||
></ha-svg-icon>
|
||||
<div class="status">
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.inclusion_finished"
|
||||
<ha-alert
|
||||
alert-type="error"
|
||||
.title=${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.inclusion_failed"
|
||||
)}
|
||||
</p>
|
||||
${this._lowSecurity
|
||||
? html`<ha-alert
|
||||
alert-type="warning"
|
||||
title="The device was added insecurely"
|
||||
>
|
||||
There was an error during secure
|
||||
inclusion. You can try again by
|
||||
excluding the device and adding it
|
||||
again.
|
||||
</ha-alert>`
|
||||
: ""}
|
||||
<a
|
||||
href=${`/config/devices/device/${
|
||||
this._device!.id
|
||||
}`}
|
||||
>
|
||||
<mwc-button>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.view_device"
|
||||
)}
|
||||
</mwc-button>
|
||||
</a>
|
||||
${this._error ||
|
||||
this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.check_logs"
|
||||
)}
|
||||
</ha-alert>
|
||||
${this._stages
|
||||
? html` <div class="stages">
|
||||
${this._stages.map(
|
||||
@ -504,18 +469,60 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
${this.hass.localize("ui.common.close")}
|
||||
</mwc-button>
|
||||
`
|
||||
: this._status === "provisioned"
|
||||
? html` <div class="flex-container">
|
||||
: this._status === "finished"
|
||||
? html`
|
||||
<div class="flex-container">
|
||||
<ha-svg-icon
|
||||
.path=${mdiCheckCircle}
|
||||
class="success"
|
||||
.path=${this._lowSecurity
|
||||
? mdiAlertCircle
|
||||
: mdiCheckCircle}
|
||||
class=${this._lowSecurity
|
||||
? "warning"
|
||||
: "success"}
|
||||
></ha-svg-icon>
|
||||
<div class="status">
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.provisioning_finished"
|
||||
"ui.panel.config.zwave_js.add_node.inclusion_finished"
|
||||
)}
|
||||
</p>
|
||||
${this._lowSecurity
|
||||
? html`<ha-alert
|
||||
alert-type="warning"
|
||||
title="The device was added insecurely"
|
||||
>
|
||||
There was an error during secure
|
||||
inclusion. You can try again by
|
||||
excluding the device and adding it
|
||||
again.
|
||||
</ha-alert>`
|
||||
: ""}
|
||||
<a
|
||||
href=${`/config/devices/device/${
|
||||
this._device?.id
|
||||
}`}
|
||||
>
|
||||
<mwc-button>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.view_device"
|
||||
)}
|
||||
</mwc-button>
|
||||
</a>
|
||||
${this._stages
|
||||
? html` <div class="stages">
|
||||
${this._stages.map(
|
||||
(stage) => html`
|
||||
<span class="stage">
|
||||
<ha-svg-icon
|
||||
.path=${mdiCheckCircle}
|
||||
class="success"
|
||||
></ha-svg-icon>
|
||||
${stage}
|
||||
</span>
|
||||
`
|
||||
)}
|
||||
</div>`
|
||||
: ""}
|
||||
</div>
|
||||
</div>
|
||||
<mwc-button
|
||||
@ -523,12 +530,42 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
@click=${this.closeDialog}
|
||||
>
|
||||
${this.hass.localize("ui.common.close")}
|
||||
</mwc-button>`
|
||||
: ""}
|
||||
</mwc-button>
|
||||
`
|
||||
: this._status === "provisioned"
|
||||
? html` <div class="flex-container">
|
||||
<ha-svg-icon
|
||||
.path=${mdiCheckCircle}
|
||||
class="success"
|
||||
></ha-svg-icon>
|
||||
<div class="status">
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.add_node.provisioning_finished"
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
@click=${this.closeDialog}
|
||||
>
|
||||
${this.hass.localize("ui.common.close")}
|
||||
</mwc-button>`
|
||||
: ""}
|
||||
</ha-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
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 {
|
||||
this._unsubscribe();
|
||||
this._status = "choose_strategy";
|
||||
@ -639,7 +676,7 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
}
|
||||
|
||||
private async _validateDskAndEnterPin(): Promise<void> {
|
||||
this._status = "loading";
|
||||
this._status = "waiting_for_device";
|
||||
this._error = undefined;
|
||||
try {
|
||||
await zwaveValidateDskAndEnterPin(
|
||||
@ -656,7 +693,7 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
}
|
||||
|
||||
private async _grantSecurityClasses(): Promise<void> {
|
||||
this._status = "loading";
|
||||
this._status = "waiting_for_device";
|
||||
this._error = undefined;
|
||||
try {
|
||||
await zwaveGrantSecurityClasses(
|
||||
@ -719,6 +756,12 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
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") {
|
||||
this._status = "validate_dsk_enter_pin";
|
||||
this._dsk = message.dsk;
|
||||
@ -775,6 +818,13 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
}, 90000);
|
||||
}
|
||||
|
||||
private _onBeforeUnload = (event: BeforeUnloadEvent) => {
|
||||
if (this._shouldPreventClose()) {
|
||||
event.preventDefault();
|
||||
}
|
||||
event.returnValue = true;
|
||||
};
|
||||
|
||||
private _unsubscribe(): void {
|
||||
if (this._subscribed) {
|
||||
this._subscribed.then((unsub) => unsub());
|
||||
@ -791,6 +841,7 @@ class DialogZWaveJSAddNode extends LitElement {
|
||||
clearTimeout(this._addNodeTimeoutHandle);
|
||||
}
|
||||
this._addNodeTimeoutHandle = undefined;
|
||||
window.removeEventListener("beforeunload", this._onBeforeUnload);
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
|
@ -4863,7 +4863,8 @@
|
||||
"provisioning_finished": "The device has been added. Once you power it on, it will become available.",
|
||||
"view_device": "View Device",
|
||||
"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": {
|
||||
"dsk": "DSK",
|
||||
|
Loading…
x
Reference in New Issue
Block a user