Handle config entry not loaded on Z-Wave JS config panel (#9451)

* Handle config entry not loaded on Z-Wave JS config panel

* Move ERROR_STATES to data/config_entries and import
This commit is contained in:
Charles Garwood 2021-06-29 19:04:42 -04:00 committed by GitHub
parent db37dffdbb
commit ed4809b71e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 117 additions and 8 deletions

View File

@ -27,6 +27,12 @@ export type ConfigEntryMutableParams = Partial<
> >
>; >;
export const ERROR_STATES: ConfigEntry["state"][] = [
"migration_error",
"setup_error",
"setup_retry",
];
export const getConfigEntries = (hass: HomeAssistant) => export const getConfigEntries = (hass: HomeAssistant) =>
hass.callApi<ConfigEntry[]>("GET", "config/config_entries/entry"); hass.callApi<ConfigEntry[]>("GET", "config/config_entries/entry");

View File

@ -22,6 +22,7 @@ import {
enableConfigEntry, enableConfigEntry,
reloadConfigEntry, reloadConfigEntry,
updateConfigEntry, updateConfigEntry,
ERROR_STATES,
} from "../../../data/config_entries"; } from "../../../data/config_entries";
import type { DeviceRegistryEntry } from "../../../data/device_registry"; import type { DeviceRegistryEntry } from "../../../data/device_registry";
import type { EntityRegistryEntry } from "../../../data/entity_registry"; import type { EntityRegistryEntry } from "../../../data/entity_registry";
@ -38,12 +39,6 @@ import type { HomeAssistant } from "../../../types";
import type { ConfigEntryExtended } from "./ha-config-integrations"; import type { ConfigEntryExtended } from "./ha-config-integrations";
import "./ha-integration-header"; import "./ha-integration-header";
const ERROR_STATES: ConfigEntry["state"][] = [
"migration_error",
"setup_error",
"setup_retry",
];
const integrationsWithPanel = { const integrationsWithPanel = {
hassio: "/hassio/dashboard", hassio: "/hassio/dashboard",
mqtt: "/config/mqtt", mqtt: "/config/mqtt",

View File

@ -1,6 +1,6 @@
import "@material/mwc-button/mwc-button"; import "@material/mwc-button/mwc-button";
import "@material/mwc-icon-button/mwc-icon-button"; import "@material/mwc-icon-button/mwc-icon-button";
import { mdiCheckCircle, mdiCircle, mdiRefresh } from "@mdi/js"; import { mdiAlertCircle, mdiCheckCircle, mdiCircle, mdiRefresh } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
@ -17,6 +17,11 @@ import {
ZWaveJSNetwork, ZWaveJSNetwork,
ZWaveJSNode, ZWaveJSNode,
} from "../../../../../data/zwave_js"; } from "../../../../../data/zwave_js";
import {
ConfigEntry,
getConfigEntries,
ERROR_STATES,
} from "../../../../../data/config_entries";
import { import {
showAlertDialog, showAlertDialog,
showConfirmationDialog, showConfirmationDialog,
@ -30,7 +35,6 @@ import { showZWaveJSAddNodeDialog } from "./show-dialog-zwave_js-add-node";
import { showZWaveJSHealNetworkDialog } from "./show-dialog-zwave_js-heal-network"; import { showZWaveJSHealNetworkDialog } from "./show-dialog-zwave_js-heal-network";
import { showZWaveJSRemoveNodeDialog } from "./show-dialog-zwave_js-remove-node"; import { showZWaveJSRemoveNodeDialog } from "./show-dialog-zwave_js-remove-node";
import { configTabs } from "./zwave_js-config-router"; import { configTabs } from "./zwave_js-config-router";
import { getConfigEntries } from "../../../../../data/config_entries";
import { showOptionsFlowDialog } from "../../../../../dialogs/config-flow/show-dialog-options-flow"; import { showOptionsFlowDialog } from "../../../../../dialogs/config-flow/show-dialog-options-flow";
@customElement("zwave_js-config-dashboard") @customElement("zwave_js-config-dashboard")
@ -45,6 +49,8 @@ class ZWaveJSConfigDashboard extends LitElement {
@property() public configEntryId?: string; @property() public configEntryId?: string;
@state() private _configEntry?: ConfigEntry;
@state() private _network?: ZWaveJSNetwork; @state() private _network?: ZWaveJSNetwork;
@state() private _nodes?: ZWaveJSNode[]; @state() private _nodes?: ZWaveJSNode[];
@ -62,6 +68,14 @@ class ZWaveJSConfigDashboard extends LitElement {
} }
protected render(): TemplateResult { protected render(): TemplateResult {
if (!this._configEntry) {
return html``;
}
if (ERROR_STATES.includes(this._configEntry.state)) {
return this._renderErrorScreen();
}
return html` return html`
<hass-tabs-subpage <hass-tabs-subpage
.hass=${this.hass} .hass=${this.hass}
@ -222,10 +236,83 @@ class ZWaveJSConfigDashboard extends LitElement {
`; `;
} }
private _renderErrorScreen() {
const item = this._configEntry!;
let stateText: [string, ...unknown[]] | undefined;
let stateTextExtra: TemplateResult | string | undefined;
if (item.disabled_by) {
stateText = [
"ui.panel.config.integrations.config_entry.disable.disabled_cause",
{
cause:
this.hass.localize(
`ui.panel.config.integrations.config_entry.disable.disabled_by.${item.disabled_by}`
) || item.disabled_by,
},
];
if (item.state === "failed_unload") {
stateTextExtra = html`.
${this.hass.localize(
"ui.panel.config.integrations.config_entry.disable_restart_confirm"
)}.`;
}
} else if (item.state === "not_loaded") {
stateText = ["ui.panel.config.integrations.config_entry.not_loaded"];
} else if (ERROR_STATES.includes(item.state)) {
stateText = [
`ui.panel.config.integrations.config_entry.state.${item.state}`,
];
if (item.reason) {
this.hass.loadBackendTranslation("config", item.domain);
stateTextExtra = html` ${this.hass.localize(
`component.${item.domain}.config.error.${item.reason}`
) || item.reason}`;
} else {
stateTextExtra = html`
<br />
<a href="/config/logs"
>${this.hass.localize(
"ui.panel.config.integrations.config_entry.check_the_logs"
)}</a
>
`;
}
}
return html` ${stateText
? html`
<div class="error-message">
<ha-svg-icon .path=${mdiAlertCircle}></ha-svg-icon>
<h3>
${this._configEntry!.title}: ${this.hass.localize(...stateText)}
</h3>
<p>${stateTextExtra}</p>
<mwc-button @click=${this._handleBack}>
${this.hass?.localize("ui.panel.error.go_back") || "go back"}
</mwc-button>
</div>
`
: ""}`;
}
private _handleBack(): void {
history.back();
}
private async _fetchData() { private async _fetchData() {
if (!this.configEntryId) { if (!this.configEntryId) {
return; return;
} }
const configEntries = await getConfigEntries(this.hass);
this._configEntry = configEntries.find(
(entry) => entry.entry_id === this.configEntryId!
);
if (ERROR_STATES.includes(this._configEntry!.state)) {
return;
}
const [network, dataCollectionStatus] = await Promise.all([ const [network, dataCollectionStatus] = await Promise.all([
fetchNetworkStatus(this.hass!, this.configEntryId), fetchNetworkStatus(this.hass!, this.configEntryId),
fetchDataCollectionStatus(this.hass!, this.configEntryId), fetchDataCollectionStatus(this.hass!, this.configEntryId),
@ -363,6 +450,27 @@ class ZWaveJSConfigDashboard extends LitElement {
color: red; color: red;
} }
.error-message {
display: flex;
color: var(--primary-text-color);
height: calc(100% - var(--header-height));
padding: 16px;
align-items: center;
justify-content: center;
flex-direction: column;
}
.error-message h3 {
text-align: center;
font-weight: bold;
}
.error-message ha-svg-icon {
color: var(--error-color);
width: 64px;
height: 64px;
}
.content { .content {
margin-top: 24px; margin-top: 24px;
} }