mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 01:36:49 +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;
|
||||
ozw_instance: number;
|
||||
event: string;
|
||||
node_manufacturer_name: string;
|
||||
node_product_name: string;
|
||||
}
|
||||
|
||||
export interface OZWDeviceMetaDataResponse {
|
||||
@ -147,6 +149,15 @@ export const fetchOZWNetworkStatistics = (
|
||||
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 = (
|
||||
hass: HomeAssistant,
|
||||
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-item-body";
|
||||
import "@material/mwc-fab";
|
||||
import {
|
||||
css,
|
||||
CSSResultArray,
|
||||
@ -14,20 +16,18 @@ import {
|
||||
import { navigate } from "../../../../../common/navigate";
|
||||
import "../../../../../components/ha-card";
|
||||
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 type { HomeAssistant, Route } from "../../../../../types";
|
||||
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[] = [];
|
||||
|
||||
@ -45,22 +45,8 @@ class OZWConfigDashboard extends LitElement {
|
||||
|
||||
@internalProperty() private _instances: OZWInstance[] = [];
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
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 firstUpdated() {
|
||||
this._fetchData();
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
@ -142,12 +128,23 @@ class OZWConfigDashboard extends LitElement {
|
||||
`;
|
||||
})}
|
||||
`
|
||||
: ``}
|
||||
: ""}
|
||||
</ha-config-section>
|
||||
</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 {
|
||||
return [
|
||||
haStyle,
|
||||
|
@ -1,10 +1,23 @@
|
||||
import { customElement, property } from "lit-element";
|
||||
import memoizeOne from "memoize-one";
|
||||
import {
|
||||
HassRouterPage,
|
||||
RouterOptions,
|
||||
} from "../../../../../layouts/hass-router-page";
|
||||
import { HomeAssistant } from "../../../../../types";
|
||||
import { navigate } from "../../../../../common/navigate";
|
||||
import { HomeAssistant, Route } from "../../../../../types";
|
||||
|
||||
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")
|
||||
class OZWConfigRouter extends HassRouterPage {
|
||||
@ -30,10 +43,10 @@ class OZWConfigRouter extends HassRouterPage {
|
||||
),
|
||||
},
|
||||
network: {
|
||||
tag: "ozw-config-network",
|
||||
tag: "ozw-network-router",
|
||||
load: () =>
|
||||
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.configEntryId = this._configEntry;
|
||||
if (this._currentPage === "network") {
|
||||
el.ozw_instance = this.routeTail.path.substr(1);
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
const path = this.routeTail.path.split("/");
|
||||
el.ozwInstance = path[1];
|
||||
el.route = computeTail(this.routeTail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import "@material/mwc-fab";
|
||||
import { mdiCheckCircle, mdiCircle, mdiCloseCircle } from "@mdi/js";
|
||||
import {
|
||||
css,
|
||||
CSSResultArray,
|
||||
@ -9,31 +11,28 @@ import {
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import { navigate } from "../../../../../common/navigate";
|
||||
import "../../../../../components/buttons/ha-call-service-button";
|
||||
import "../../../../../components/ha-card";
|
||||
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 type { HomeAssistant, Route } from "../../../../../types";
|
||||
import "../../../ha-config-section";
|
||||
import { mdiCircle, mdiCheckCircle, mdiCloseCircle } from "@mdi/js";
|
||||
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";
|
||||
import { ozwNetworkTabs } from "./ozw-network-router";
|
||||
|
||||
export const ozwTabs: PageNavigation[] = [];
|
||||
|
||||
@customElement("ozw-config-network")
|
||||
class OZWConfigNetwork extends LitElement {
|
||||
@customElement("ozw-network-dashboard")
|
||||
class OZWNetworkDashboard extends LitElement {
|
||||
@property({ type: Object }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ type: Object }) public route!: Route;
|
||||
@ -44,7 +43,7 @@ class OZWConfigNetwork extends LitElement {
|
||||
|
||||
@property() public configEntryId?: string;
|
||||
|
||||
@property() public ozw_instance = 0;
|
||||
@property() public ozwInstance?: number;
|
||||
|
||||
@internalProperty() private _network?: OZWInstance;
|
||||
|
||||
@ -54,54 +53,21 @@ class OZWConfigNetwork extends LitElement {
|
||||
|
||||
@internalProperty() private _icon = mdiCircle;
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
if (this.ozw_instance <= 0) {
|
||||
protected firstUpdated() {
|
||||
if (!this.ozwInstance) {
|
||||
navigate(this, "/config/ozw/dashboard", true);
|
||||
}
|
||||
if (this.hass) {
|
||||
} else if (this.hass) {
|
||||
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 {
|
||||
return html`
|
||||
<hass-tabs-subpage
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.route=${this.route}
|
||||
.tabs=${ozwTabs}
|
||||
.tabs=${ozwNetworkTabs(this.ozwInstance!)}
|
||||
>
|
||||
<ha-config-section .narrow=${this.narrow} .isWide=${this.isWide}>
|
||||
<div slot="header">
|
||||
@ -118,20 +84,21 @@ class OZWConfigNetwork extends LitElement {
|
||||
<div class="details">
|
||||
<ha-svg-icon
|
||||
.path=${this._icon}
|
||||
class="network-status-icon ${this._status}"
|
||||
class="network-status-icon ${classMap({
|
||||
[this._status]: true,
|
||||
})}"
|
||||
slot="item-icon"
|
||||
></ha-svg-icon>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.ozw.common.network"
|
||||
)}
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.ozw.network_status." + this._status
|
||||
`ui.panel.config.ozw.network_status.${this._status}`
|
||||
)}
|
||||
<br />
|
||||
<small>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.ozw.network_status.details." +
|
||||
this._network.Status.toLowerCase()
|
||||
`ui.panel.config.ozw.network_status.details.${this._network.Status.toLowerCase()}`
|
||||
)}
|
||||
</small>
|
||||
</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 {
|
||||
return [
|
||||
haStyle,
|
||||
@ -248,6 +247,6 @@ class OZWConfigNetwork extends LitElement {
|
||||
|
||||
declare global {
|
||||
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.",
|
||||
"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": {
|
||||
"add_node": "Add Node",
|
||||
"remove_node": "Remove Node"
|
||||
|
Loading…
x
Reference in New Issue
Block a user