mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-26 02:36:37 +00:00
Add basic nodes list & node metadata to OZW config panel (#6719)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
793b9f238c
commit
aa5e20df05
@ -14,6 +14,8 @@ export interface OZWDevice {
|
|||||||
is_zwave_plus: boolean;
|
is_zwave_plus: boolean;
|
||||||
ozw_instance: number;
|
ozw_instance: number;
|
||||||
event: string;
|
event: string;
|
||||||
|
node_manufacturer_name: string;
|
||||||
|
node_product_name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OZWDeviceMetaDataResponse {
|
export interface OZWDeviceMetaDataResponse {
|
||||||
@ -147,6 +149,15 @@ export const fetchOZWNetworkStatistics = (
|
|||||||
ozw_instance: ozw_instance,
|
ozw_instance: ozw_instance,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const fetchOZWNodes = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
ozw_instance: number
|
||||||
|
): Promise<OZWDevice[]> =>
|
||||||
|
hass.callWS({
|
||||||
|
type: "ozw/get_nodes",
|
||||||
|
ozw_instance: ozw_instance,
|
||||||
|
});
|
||||||
|
|
||||||
export const fetchOZWNodeStatus = (
|
export const fetchOZWNodeStatus = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
ozw_instance: number,
|
ozw_instance: number,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
import "@material/mwc-button/mwc-button";
|
||||||
|
import "@material/mwc-fab";
|
||||||
|
import { mdiCheckCircle, mdiCircle, mdiCloseCircle, mdiZWave } from "@mdi/js";
|
||||||
import "@polymer/paper-item/paper-icon-item";
|
import "@polymer/paper-item/paper-icon-item";
|
||||||
import "@polymer/paper-item/paper-item-body";
|
import "@polymer/paper-item/paper-item-body";
|
||||||
import "@material/mwc-fab";
|
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResultArray,
|
CSSResultArray,
|
||||||
@ -14,20 +16,18 @@ import {
|
|||||||
import { navigate } from "../../../../../common/navigate";
|
import { navigate } from "../../../../../common/navigate";
|
||||||
import "../../../../../components/ha-card";
|
import "../../../../../components/ha-card";
|
||||||
import "../../../../../components/ha-icon-next";
|
import "../../../../../components/ha-icon-next";
|
||||||
|
import {
|
||||||
|
fetchOZWInstances,
|
||||||
|
networkOfflineStatuses,
|
||||||
|
networkOnlineStatuses,
|
||||||
|
networkStartingStatuses,
|
||||||
|
OZWInstance,
|
||||||
|
} from "../../../../../data/ozw";
|
||||||
|
import "../../../../../layouts/hass-tabs-subpage";
|
||||||
|
import type { PageNavigation } from "../../../../../layouts/hass-tabs-subpage";
|
||||||
import { haStyle } from "../../../../../resources/styles";
|
import { haStyle } from "../../../../../resources/styles";
|
||||||
import type { HomeAssistant, Route } from "../../../../../types";
|
import type { HomeAssistant, Route } from "../../../../../types";
|
||||||
import "../../../ha-config-section";
|
import "../../../ha-config-section";
|
||||||
import { mdiCircle, mdiCheckCircle, mdiCloseCircle, mdiZWave } from "@mdi/js";
|
|
||||||
import "../../../../../layouts/hass-tabs-subpage";
|
|
||||||
import type { PageNavigation } from "../../../../../layouts/hass-tabs-subpage";
|
|
||||||
import "@material/mwc-button/mwc-button";
|
|
||||||
import {
|
|
||||||
OZWInstance,
|
|
||||||
fetchOZWInstances,
|
|
||||||
networkOnlineStatuses,
|
|
||||||
networkOfflineStatuses,
|
|
||||||
networkStartingStatuses,
|
|
||||||
} from "../../../../../data/ozw";
|
|
||||||
|
|
||||||
export const ozwTabs: PageNavigation[] = [];
|
export const ozwTabs: PageNavigation[] = [];
|
||||||
|
|
||||||
@ -45,22 +45,8 @@ class OZWConfigDashboard extends LitElement {
|
|||||||
|
|
||||||
@internalProperty() private _instances: OZWInstance[] = [];
|
@internalProperty() private _instances: OZWInstance[] = [];
|
||||||
|
|
||||||
public connectedCallback(): void {
|
protected firstUpdated() {
|
||||||
super.connectedCallback();
|
this._fetchData();
|
||||||
if (this.hass) {
|
|
||||||
this._fetchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _fetchData() {
|
|
||||||
this._instances = await fetchOZWInstances(this.hass!);
|
|
||||||
if (this._instances.length === 1) {
|
|
||||||
navigate(
|
|
||||||
this,
|
|
||||||
`/config/ozw/network/${this._instances[0].ozw_instance}`,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
@ -142,12 +128,23 @@ class OZWConfigDashboard extends LitElement {
|
|||||||
`;
|
`;
|
||||||
})}
|
})}
|
||||||
`
|
`
|
||||||
: ``}
|
: ""}
|
||||||
</ha-config-section>
|
</ha-config-section>
|
||||||
</hass-tabs-subpage>
|
</hass-tabs-subpage>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _fetchData() {
|
||||||
|
this._instances = await fetchOZWInstances(this.hass!);
|
||||||
|
if (this._instances.length === 1) {
|
||||||
|
navigate(
|
||||||
|
this,
|
||||||
|
`/config/ozw/network/${this._instances[0].ozw_instance}`,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultArray {
|
static get styles(): CSSResultArray {
|
||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
|
@ -1,10 +1,23 @@
|
|||||||
import { customElement, property } from "lit-element";
|
import { customElement, property } from "lit-element";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
import {
|
import {
|
||||||
HassRouterPage,
|
HassRouterPage,
|
||||||
RouterOptions,
|
RouterOptions,
|
||||||
} from "../../../../../layouts/hass-router-page";
|
} from "../../../../../layouts/hass-router-page";
|
||||||
import { HomeAssistant } from "../../../../../types";
|
import { HomeAssistant, Route } from "../../../../../types";
|
||||||
import { navigate } from "../../../../../common/navigate";
|
|
||||||
|
export const computeTail = memoizeOne((route: Route) => {
|
||||||
|
const dividerPos = route.path.indexOf("/", 1);
|
||||||
|
return dividerPos === -1
|
||||||
|
? {
|
||||||
|
prefix: route.prefix + route.path,
|
||||||
|
path: "",
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
prefix: route.prefix + route.path.substr(0, dividerPos),
|
||||||
|
path: route.path.substr(dividerPos),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
@customElement("ozw-config-router")
|
@customElement("ozw-config-router")
|
||||||
class OZWConfigRouter extends HassRouterPage {
|
class OZWConfigRouter extends HassRouterPage {
|
||||||
@ -30,10 +43,10 @@ class OZWConfigRouter extends HassRouterPage {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
network: {
|
network: {
|
||||||
tag: "ozw-config-network",
|
tag: "ozw-network-router",
|
||||||
load: () =>
|
load: () =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "ozw-config-network" */ "./ozw-config-network"
|
/* webpackChunkName: "ozw-network-router" */ "./ozw-network-router"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -46,19 +59,9 @@ class OZWConfigRouter extends HassRouterPage {
|
|||||||
el.narrow = this.narrow;
|
el.narrow = this.narrow;
|
||||||
el.configEntryId = this._configEntry;
|
el.configEntryId = this._configEntry;
|
||||||
if (this._currentPage === "network") {
|
if (this._currentPage === "network") {
|
||||||
el.ozw_instance = this.routeTail.path.substr(1);
|
const path = this.routeTail.path.split("/");
|
||||||
}
|
el.ozwInstance = path[1];
|
||||||
|
el.route = computeTail(this.routeTail);
|
||||||
const searchParams = new URLSearchParams(window.location.search);
|
|
||||||
if (this._configEntry && !searchParams.has("config_entry")) {
|
|
||||||
searchParams.append("config_entry", this._configEntry);
|
|
||||||
navigate(
|
|
||||||
this,
|
|
||||||
`${this.routeTail.prefix}${
|
|
||||||
this.routeTail.path
|
|
||||||
}?${searchParams.toString()}`,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
import "@material/mwc-button/mwc-button";
|
||||||
import "@material/mwc-fab";
|
import "@material/mwc-fab";
|
||||||
|
import { mdiCheckCircle, mdiCircle, mdiCloseCircle } from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResultArray,
|
CSSResultArray,
|
||||||
@ -9,31 +11,28 @@ import {
|
|||||||
property,
|
property,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
import { navigate } from "../../../../../common/navigate";
|
import { navigate } from "../../../../../common/navigate";
|
||||||
|
import "../../../../../components/buttons/ha-call-service-button";
|
||||||
import "../../../../../components/ha-card";
|
import "../../../../../components/ha-card";
|
||||||
import "../../../../../components/ha-icon-next";
|
import "../../../../../components/ha-icon-next";
|
||||||
import "../../../../../components/buttons/ha-call-service-button";
|
import {
|
||||||
|
fetchOZWNetworkStatistics,
|
||||||
|
fetchOZWNetworkStatus,
|
||||||
|
networkOfflineStatuses,
|
||||||
|
networkOnlineStatuses,
|
||||||
|
networkStartingStatuses,
|
||||||
|
OZWInstance,
|
||||||
|
OZWNetworkStatistics,
|
||||||
|
} from "../../../../../data/ozw";
|
||||||
|
import "../../../../../layouts/hass-tabs-subpage";
|
||||||
import { haStyle } from "../../../../../resources/styles";
|
import { haStyle } from "../../../../../resources/styles";
|
||||||
import type { HomeAssistant, Route } from "../../../../../types";
|
import type { HomeAssistant, Route } from "../../../../../types";
|
||||||
import "../../../ha-config-section";
|
import "../../../ha-config-section";
|
||||||
import { mdiCircle, mdiCheckCircle, mdiCloseCircle } from "@mdi/js";
|
import { ozwNetworkTabs } from "./ozw-network-router";
|
||||||
import "../../../../../layouts/hass-tabs-subpage";
|
|
||||||
import type { PageNavigation } from "../../../../../layouts/hass-tabs-subpage";
|
|
||||||
import "@material/mwc-button/mwc-button";
|
|
||||||
import {
|
|
||||||
OZWInstance,
|
|
||||||
fetchOZWNetworkStatus,
|
|
||||||
fetchOZWNetworkStatistics,
|
|
||||||
networkOnlineStatuses,
|
|
||||||
networkOfflineStatuses,
|
|
||||||
networkStartingStatuses,
|
|
||||||
OZWNetworkStatistics,
|
|
||||||
} from "../../../../../data/ozw";
|
|
||||||
|
|
||||||
export const ozwTabs: PageNavigation[] = [];
|
@customElement("ozw-network-dashboard")
|
||||||
|
class OZWNetworkDashboard extends LitElement {
|
||||||
@customElement("ozw-config-network")
|
|
||||||
class OZWConfigNetwork extends LitElement {
|
|
||||||
@property({ type: Object }) public hass!: HomeAssistant;
|
@property({ type: Object }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ type: Object }) public route!: Route;
|
@property({ type: Object }) public route!: Route;
|
||||||
@ -44,7 +43,7 @@ class OZWConfigNetwork extends LitElement {
|
|||||||
|
|
||||||
@property() public configEntryId?: string;
|
@property() public configEntryId?: string;
|
||||||
|
|
||||||
@property() public ozw_instance = 0;
|
@property() public ozwInstance?: number;
|
||||||
|
|
||||||
@internalProperty() private _network?: OZWInstance;
|
@internalProperty() private _network?: OZWInstance;
|
||||||
|
|
||||||
@ -54,54 +53,21 @@ class OZWConfigNetwork extends LitElement {
|
|||||||
|
|
||||||
@internalProperty() private _icon = mdiCircle;
|
@internalProperty() private _icon = mdiCircle;
|
||||||
|
|
||||||
public connectedCallback(): void {
|
protected firstUpdated() {
|
||||||
super.connectedCallback();
|
if (!this.ozwInstance) {
|
||||||
if (this.ozw_instance <= 0) {
|
|
||||||
navigate(this, "/config/ozw/dashboard", true);
|
navigate(this, "/config/ozw/dashboard", true);
|
||||||
}
|
} else if (this.hass) {
|
||||||
if (this.hass) {
|
|
||||||
this._fetchData();
|
this._fetchData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _fetchData() {
|
|
||||||
this._network = await fetchOZWNetworkStatus(this.hass!, this.ozw_instance);
|
|
||||||
this._statistics = await fetchOZWNetworkStatistics(
|
|
||||||
this.hass!,
|
|
||||||
this.ozw_instance
|
|
||||||
);
|
|
||||||
if (networkOnlineStatuses.includes(this._network.Status)) {
|
|
||||||
this._status = "online";
|
|
||||||
this._icon = mdiCheckCircle;
|
|
||||||
}
|
|
||||||
if (networkStartingStatuses.includes(this._network.Status)) {
|
|
||||||
this._status = "starting";
|
|
||||||
}
|
|
||||||
if (networkOfflineStatuses.includes(this._network.Status)) {
|
|
||||||
this._status = "offline";
|
|
||||||
this._icon = mdiCloseCircle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _generateServiceButton(service: string) {
|
|
||||||
return html`
|
|
||||||
<ha-call-service-button
|
|
||||||
.hass=${this.hass}
|
|
||||||
domain="ozw"
|
|
||||||
service="${service}"
|
|
||||||
>
|
|
||||||
${this.hass!.localize("ui.panel.config.ozw.services." + service)}
|
|
||||||
</ha-call-service-button>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<hass-tabs-subpage
|
<hass-tabs-subpage
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
.route=${this.route}
|
.route=${this.route}
|
||||||
.tabs=${ozwTabs}
|
.tabs=${ozwNetworkTabs(this.ozwInstance!)}
|
||||||
>
|
>
|
||||||
<ha-config-section .narrow=${this.narrow} .isWide=${this.isWide}>
|
<ha-config-section .narrow=${this.narrow} .isWide=${this.isWide}>
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
@ -118,20 +84,21 @@ class OZWConfigNetwork extends LitElement {
|
|||||||
<div class="details">
|
<div class="details">
|
||||||
<ha-svg-icon
|
<ha-svg-icon
|
||||||
.path=${this._icon}
|
.path=${this._icon}
|
||||||
class="network-status-icon ${this._status}"
|
class="network-status-icon ${classMap({
|
||||||
|
[this._status]: true,
|
||||||
|
})}"
|
||||||
slot="item-icon"
|
slot="item-icon"
|
||||||
></ha-svg-icon>
|
></ha-svg-icon>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.ozw.common.network"
|
"ui.panel.config.ozw.common.network"
|
||||||
)}
|
)}
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.ozw.network_status." + this._status
|
`ui.panel.config.ozw.network_status.${this._status}`
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
<small>
|
<small>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.ozw.network_status.details." +
|
`ui.panel.config.ozw.network_status.details.${this._network.Status.toLowerCase()}`
|
||||||
this._network.Status.toLowerCase()
|
|
||||||
)}
|
)}
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
@ -171,6 +138,38 @@ class OZWConfigNetwork extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _fetchData() {
|
||||||
|
if (!this.ozwInstance) return;
|
||||||
|
this._network = await fetchOZWNetworkStatus(this.hass!, this.ozwInstance);
|
||||||
|
this._statistics = await fetchOZWNetworkStatistics(
|
||||||
|
this.hass!,
|
||||||
|
this.ozwInstance
|
||||||
|
);
|
||||||
|
if (networkOnlineStatuses.includes(this._network!.Status)) {
|
||||||
|
this._status = "online";
|
||||||
|
this._icon = mdiCheckCircle;
|
||||||
|
}
|
||||||
|
if (networkStartingStatuses.includes(this._network!.Status)) {
|
||||||
|
this._status = "starting";
|
||||||
|
}
|
||||||
|
if (networkOfflineStatuses.includes(this._network!.Status)) {
|
||||||
|
this._status = "offline";
|
||||||
|
this._icon = mdiCloseCircle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _generateServiceButton(service: string) {
|
||||||
|
return html`
|
||||||
|
<ha-call-service-button
|
||||||
|
.hass=${this.hass}
|
||||||
|
domain="ozw"
|
||||||
|
.service=${service}
|
||||||
|
>
|
||||||
|
${this.hass!.localize(`ui.panel.config.ozw.services.${service}`)}
|
||||||
|
</ha-call-service-button>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultArray {
|
static get styles(): CSSResultArray {
|
||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
@ -248,6 +247,6 @@ class OZWConfigNetwork extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"ozw-config-network": OZWConfigNetwork;
|
"ozw-network-dashboard": OZWNetworkDashboard;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,144 @@
|
|||||||
|
import "@material/mwc-button/mwc-button";
|
||||||
|
import "@material/mwc-fab";
|
||||||
|
import { mdiAlert, mdiCheck } from "@mdi/js";
|
||||||
|
import {
|
||||||
|
CSSResult,
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
internalProperty,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
|
import { navigate } from "../../../../../common/navigate";
|
||||||
|
import "../../../../../components/buttons/ha-call-service-button";
|
||||||
|
import { HASSDomEvent } from "../../../../../common/dom/fire_event";
|
||||||
|
import {
|
||||||
|
DataTableColumnContainer,
|
||||||
|
RowClickedEvent,
|
||||||
|
} from "../../../../../components/data-table/ha-data-table";
|
||||||
|
import "../../../../../components/ha-card";
|
||||||
|
import "../../../../../components/ha-icon-next";
|
||||||
|
import { fetchOZWNodes, OZWDevice } from "../../../../../data/ozw";
|
||||||
|
import "../../../../../layouts/hass-tabs-subpage";
|
||||||
|
import "../../../../../layouts/hass-tabs-subpage-data-table";
|
||||||
|
import { haStyle } from "../../../../../resources/styles";
|
||||||
|
import type { HomeAssistant, Route } from "../../../../../types";
|
||||||
|
import "../../../ha-config-section";
|
||||||
|
import { ozwNetworkTabs } from "./ozw-network-router";
|
||||||
|
|
||||||
|
export interface NodeRowData extends OZWDevice {
|
||||||
|
node?: NodeRowData;
|
||||||
|
id?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
@customElement("ozw-network-nodes")
|
||||||
|
class OZWNetworkNodes extends LitElement {
|
||||||
|
@property({ type: Object }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ type: Object }) public route!: Route;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow!: boolean;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public isWide!: boolean;
|
||||||
|
|
||||||
|
@property() public configEntryId?: string;
|
||||||
|
|
||||||
|
@property() public ozwInstance = 0;
|
||||||
|
|
||||||
|
@internalProperty() private _nodes: OZWDevice[] = [];
|
||||||
|
|
||||||
|
private _columns = memoizeOne(
|
||||||
|
(narrow: boolean): DataTableColumnContainer => {
|
||||||
|
return {
|
||||||
|
node_id: {
|
||||||
|
title: this.hass.localize("ui.panel.config.ozw.nodes_table.id"),
|
||||||
|
sortable: true,
|
||||||
|
type: "numeric",
|
||||||
|
width: "72px",
|
||||||
|
filterable: true,
|
||||||
|
direction: "asc",
|
||||||
|
},
|
||||||
|
node_product_name: {
|
||||||
|
title: this.hass.localize("ui.panel.config.ozw.nodes_table.model"),
|
||||||
|
sortable: true,
|
||||||
|
width: narrow ? "75%" : "25%",
|
||||||
|
},
|
||||||
|
node_manufacturer_name: {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.panel.config.ozw.nodes_table.manufacturer"
|
||||||
|
),
|
||||||
|
sortable: true,
|
||||||
|
hidden: narrow,
|
||||||
|
width: "25%",
|
||||||
|
},
|
||||||
|
node_query_stage: {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.panel.config.ozw.nodes_table.query_stage"
|
||||||
|
),
|
||||||
|
sortable: true,
|
||||||
|
width: narrow ? "25%" : "15%",
|
||||||
|
},
|
||||||
|
is_zwave_plus: {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.panel.config.ozw.nodes_table.zwave_plus"
|
||||||
|
),
|
||||||
|
hidden: narrow,
|
||||||
|
template: (value: boolean) =>
|
||||||
|
value ? html` <ha-svg-icon .path=${mdiCheck}></ha-svg-icon>` : "",
|
||||||
|
},
|
||||||
|
is_failed: {
|
||||||
|
title: this.hass.localize("ui.panel.config.ozw.nodes_table.failed"),
|
||||||
|
hidden: narrow,
|
||||||
|
template: (value: boolean) =>
|
||||||
|
value ? html` <ha-svg-icon .path=${mdiAlert}></ha-svg-icon>` : "",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
protected firstUpdated() {
|
||||||
|
if (!this.ozwInstance) {
|
||||||
|
navigate(this, "/config/ozw/dashboard", true);
|
||||||
|
} else if (this.hass) {
|
||||||
|
this._fetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<hass-tabs-subpage-data-table
|
||||||
|
.hass=${this.hass}
|
||||||
|
.narrow=${this.narrow}
|
||||||
|
.route=${this.route}
|
||||||
|
.tabs=${ozwNetworkTabs(this.ozwInstance)}
|
||||||
|
.columns=${this._columns(this.narrow)}
|
||||||
|
.data=${this._nodes}
|
||||||
|
id="node_id"
|
||||||
|
@row-click=${this._handleRowClicked}
|
||||||
|
back-path="/config/ozw/network/${this.ozwInstance}/dashboard"
|
||||||
|
>
|
||||||
|
</hass-tabs-subpage-data-table>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _fetchData() {
|
||||||
|
this._nodes = await fetchOZWNodes(this.hass!, this.ozwInstance!);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleRowClicked(ev: HASSDomEvent<RowClickedEvent>) {
|
||||||
|
const nodeId = ev.detail.id;
|
||||||
|
navigate(this, `/config/ozw/network/${this.ozwInstance}/node/${nodeId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return haStyle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ozw-network-nodes": OZWNetworkNodes;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
import { customElement, property } from "lit-element";
|
||||||
|
import {
|
||||||
|
HassRouterPage,
|
||||||
|
RouterOptions,
|
||||||
|
} from "../../../../../layouts/hass-router-page";
|
||||||
|
import { HomeAssistant } from "../../../../../types";
|
||||||
|
import { computeTail } from "./ozw-config-router";
|
||||||
|
import { PageNavigation } from "../../../../../layouts/hass-tabs-subpage";
|
||||||
|
import { mdiServerNetwork, mdiNetwork } from "@mdi/js";
|
||||||
|
|
||||||
|
export const ozwNetworkTabs = (instance: number): PageNavigation[] => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
translationKey: "ui.panel.config.ozw.navigation.network",
|
||||||
|
path: `/config/ozw/network/${instance}/dashboard`,
|
||||||
|
iconPath: mdiServerNetwork,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
translationKey: "ui.panel.config.ozw.navigation.nodes",
|
||||||
|
path: `/config/ozw/network/${instance}/nodes`,
|
||||||
|
iconPath: mdiNetwork,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
@customElement("ozw-network-router")
|
||||||
|
class OZWNetworkRouter extends HassRouterPage {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() public isWide!: boolean;
|
||||||
|
|
||||||
|
@property() public narrow!: boolean;
|
||||||
|
|
||||||
|
@property() public ozwInstance!: number;
|
||||||
|
|
||||||
|
private _configEntry = new URLSearchParams(window.location.search).get(
|
||||||
|
"config_entry"
|
||||||
|
);
|
||||||
|
|
||||||
|
protected routerOptions: RouterOptions = {
|
||||||
|
defaultPage: "dashboard",
|
||||||
|
showLoading: true,
|
||||||
|
routes: {
|
||||||
|
dashboard: {
|
||||||
|
tag: "ozw-network-dashboard",
|
||||||
|
load: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "ozw-network-dashboard" */ "./ozw-network-dashboard"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
tag: "ozw-network-nodes",
|
||||||
|
load: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "ozw-network-nodes" */ "./ozw-network-nodes"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
node: {
|
||||||
|
tag: "ozw-node-router",
|
||||||
|
load: () =>
|
||||||
|
import(/* webpackChunkName: "ozw-node-router" */ "./ozw-node-router"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
protected updatePageEl(el): void {
|
||||||
|
el.route = computeTail(this.routeTail);
|
||||||
|
el.hass = this.hass;
|
||||||
|
el.isWide = this.isWide;
|
||||||
|
el.narrow = this.narrow;
|
||||||
|
el.configEntryId = this._configEntry;
|
||||||
|
el.ozwInstance = this.ozwInstance;
|
||||||
|
if (this._currentPage === "node") {
|
||||||
|
el.nodeId = this.routeTail.path.split("/")[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ozw-network-router": OZWNetworkRouter;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,231 @@
|
|||||||
|
import "@material/mwc-button/mwc-button";
|
||||||
|
import "@material/mwc-fab";
|
||||||
|
import {
|
||||||
|
css,
|
||||||
|
CSSResultArray,
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
internalProperty,
|
||||||
|
property,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import { navigate } from "../../../../../common/navigate";
|
||||||
|
import "../../../../../components/buttons/ha-call-service-button";
|
||||||
|
import "../../../../../components/ha-card";
|
||||||
|
import "../../../../../components/ha-icon-next";
|
||||||
|
import "../../../../../layouts/hass-tabs-subpage";
|
||||||
|
import { haStyle } from "../../../../../resources/styles";
|
||||||
|
import type { HomeAssistant, Route } from "../../../../../types";
|
||||||
|
import "../../../ha-config-section";
|
||||||
|
import {
|
||||||
|
fetchOZWNodeStatus,
|
||||||
|
fetchOZWNodeMetadata,
|
||||||
|
OZWDevice,
|
||||||
|
OZWDeviceMetaDataResponse,
|
||||||
|
} from "../../../../../data/ozw";
|
||||||
|
import { ERR_NOT_FOUND } from "../../../../../data/websocket_api";
|
||||||
|
import { showOZWRefreshNodeDialog } from "./show-dialog-ozw-refresh-node";
|
||||||
|
import { ozwNetworkTabs } from "./ozw-network-router";
|
||||||
|
|
||||||
|
@customElement("ozw-node-dashboard")
|
||||||
|
class OZWNodeDashboard extends LitElement {
|
||||||
|
@property({ type: Object }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ type: Object }) public route!: Route;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow!: boolean;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public isWide!: boolean;
|
||||||
|
|
||||||
|
@property() public configEntryId?: string;
|
||||||
|
|
||||||
|
@property() public ozwInstance?;
|
||||||
|
|
||||||
|
@property() public nodeId?;
|
||||||
|
|
||||||
|
@internalProperty() private _node?: OZWDevice;
|
||||||
|
|
||||||
|
@internalProperty() private _metadata?: OZWDeviceMetaDataResponse;
|
||||||
|
|
||||||
|
@internalProperty() private _not_found = false;
|
||||||
|
|
||||||
|
protected firstUpdated() {
|
||||||
|
if (!this.ozwInstance) {
|
||||||
|
navigate(this, "/config/ozw/dashboard", true);
|
||||||
|
} else if (!this.nodeId) {
|
||||||
|
navigate(this, `/config/ozw/network/${this.ozwInstance}/nodes`, true);
|
||||||
|
} else if (this.hass) {
|
||||||
|
this._fetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
if (this._not_found) {
|
||||||
|
return html`
|
||||||
|
<hass-error-screen
|
||||||
|
.error="${this.hass.localize("ui.panel.config.ozw.node.not_found")}"
|
||||||
|
></hass-error-screen>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<hass-tabs-subpage
|
||||||
|
.hass=${this.hass}
|
||||||
|
.narrow=${this.narrow}
|
||||||
|
.route=${this.route}
|
||||||
|
.tabs=${ozwNetworkTabs(this.ozwInstance)}
|
||||||
|
>
|
||||||
|
<ha-config-section .narrow=${this.narrow} .isWide=${this.isWide}>
|
||||||
|
<div slot="header">
|
||||||
|
Node Management
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div slot="introduction">
|
||||||
|
View the status of a node and manage its configuration.
|
||||||
|
</div>
|
||||||
|
${this._node
|
||||||
|
? html`
|
||||||
|
<ha-card class="content">
|
||||||
|
<div class="card-content">
|
||||||
|
<b
|
||||||
|
>${this._node.node_manufacturer_name}
|
||||||
|
${this._node.node_product_name}</b
|
||||||
|
><br />
|
||||||
|
Node ID: ${this._node.node_id}<br />
|
||||||
|
Query Stage: ${this._node.node_query_stage}
|
||||||
|
${this._metadata?.metadata.ProductManualURL
|
||||||
|
? html` <a
|
||||||
|
href="${this._metadata.metadata.ProductManualURL}"
|
||||||
|
>
|
||||||
|
<p>Product Manual</p>
|
||||||
|
</a>`
|
||||||
|
: ``}
|
||||||
|
</div>
|
||||||
|
<div class="card-actions">
|
||||||
|
<mwc-button @click=${this._refreshNodeClicked}>
|
||||||
|
Refresh Node
|
||||||
|
</mwc-button>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
|
||||||
|
${this._metadata
|
||||||
|
? html`
|
||||||
|
<ha-card class="content" header="Description">
|
||||||
|
<div class="card-content">
|
||||||
|
${this._metadata.metadata.Description}
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
<ha-card class="content" header="Inclusion">
|
||||||
|
<div class="card-content">
|
||||||
|
${this._metadata.metadata.InclusionHelp}
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
<ha-card class="content" header="Exclusion">
|
||||||
|
<div class="card-content">
|
||||||
|
${this._metadata.metadata.ExclusionHelp}
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
<ha-card class="content" header="Reset">
|
||||||
|
<div class="card-content">
|
||||||
|
${this._metadata.metadata.ResetHelp}
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
<ha-card class="content" header="WakeUp">
|
||||||
|
<div class="card-content">
|
||||||
|
${this._metadata.metadata.WakeupHelp}
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`
|
||||||
|
: ``}
|
||||||
|
`
|
||||||
|
: ``}
|
||||||
|
</ha-config-section>
|
||||||
|
</hass-tabs-subpage>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _fetchData() {
|
||||||
|
if (!this.ozwInstance || !this.nodeId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this._node = await fetchOZWNodeStatus(
|
||||||
|
this.hass!,
|
||||||
|
this.ozwInstance,
|
||||||
|
this.nodeId
|
||||||
|
);
|
||||||
|
this._metadata = await fetchOZWNodeMetadata(
|
||||||
|
this.hass!,
|
||||||
|
this.ozwInstance,
|
||||||
|
this.nodeId
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
if (err.code === ERR_NOT_FOUND) {
|
||||||
|
this._not_found = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _refreshNodeClicked() {
|
||||||
|
showOZWRefreshNodeDialog(this, {
|
||||||
|
node_id: this.nodeId,
|
||||||
|
ozw_instance: this.ozwInstance,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultArray {
|
||||||
|
return [
|
||||||
|
haStyle,
|
||||||
|
css`
|
||||||
|
.secondary {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionHeader {
|
||||||
|
position: relative;
|
||||||
|
padding-right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-card {
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-actions.warning ha-call-service-button {
|
||||||
|
color: var(--error-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-help-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
right: 0;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-service-description {
|
||||||
|
display: block;
|
||||||
|
color: grey;
|
||||||
|
padding: 0 8px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ozw-node-dashboard": OZWNodeDashboard;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
import { customElement, property } from "lit-element";
|
||||||
|
import { navigate } from "../../../../../common/navigate";
|
||||||
|
import {
|
||||||
|
HassRouterPage,
|
||||||
|
RouterOptions,
|
||||||
|
} from "../../../../../layouts/hass-router-page";
|
||||||
|
import { HomeAssistant } from "../../../../../types";
|
||||||
|
|
||||||
|
@customElement("ozw-node-router")
|
||||||
|
class OZWNodeRouter extends HassRouterPage {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() public isWide!: boolean;
|
||||||
|
|
||||||
|
@property() public narrow!: boolean;
|
||||||
|
|
||||||
|
@property() public ozwInstance!: number;
|
||||||
|
|
||||||
|
@property() public nodeId!: number;
|
||||||
|
|
||||||
|
private _configEntry = new URLSearchParams(window.location.search).get(
|
||||||
|
"config_entry"
|
||||||
|
);
|
||||||
|
|
||||||
|
protected routerOptions: RouterOptions = {
|
||||||
|
defaultPage: "dashboard",
|
||||||
|
showLoading: true,
|
||||||
|
routes: {
|
||||||
|
dashboard: {
|
||||||
|
tag: "ozw-node-dashboard",
|
||||||
|
load: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "ozw-node-dashboard" */ "./ozw-node-dashboard"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
protected updatePageEl(el): void {
|
||||||
|
el.route = this.routeTail;
|
||||||
|
el.hass = this.hass;
|
||||||
|
el.isWide = this.isWide;
|
||||||
|
el.narrow = this.narrow;
|
||||||
|
el.configEntryId = this._configEntry;
|
||||||
|
el.ozwInstance = this.ozwInstance;
|
||||||
|
el.nodeId = this.nodeId;
|
||||||
|
|
||||||
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
|
if (this._configEntry && !searchParams.has("config_entry")) {
|
||||||
|
searchParams.append("config_entry", this._configEntry);
|
||||||
|
navigate(
|
||||||
|
this,
|
||||||
|
`${this.routeTail.prefix}${
|
||||||
|
this.routeTail.path
|
||||||
|
}?${searchParams.toString()}`,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ozw-node-router": OZWNodeRouter;
|
||||||
|
}
|
||||||
|
}
|
@ -1804,6 +1804,17 @@
|
|||||||
"introduction": "Manage network-wide functions.",
|
"introduction": "Manage network-wide functions.",
|
||||||
"node_count": "{count} nodes"
|
"node_count": "{count} nodes"
|
||||||
},
|
},
|
||||||
|
"nodes_table": {
|
||||||
|
"id": "ID",
|
||||||
|
"manufacturer": "Manufacturer",
|
||||||
|
"model": "Model",
|
||||||
|
"query_stage": "Query Stage",
|
||||||
|
"zwave_plus": "Z-Wave Plus",
|
||||||
|
"failed": "Failed"
|
||||||
|
},
|
||||||
|
"node": {
|
||||||
|
"not_found": "Node not found"
|
||||||
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"add_node": "Add Node",
|
"add_node": "Add Node",
|
||||||
"remove_node": "Remove Node"
|
"remove_node": "Remove Node"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user