mirror of
https://github.com/chirpstack/chirpstack.git
synced 2025-05-10 04:43:09 +00:00
ui: Fix useEffect dependency warnings.
This commit is contained in:
parent
984a86cc7a
commit
9453ab7e00
@ -12,29 +12,29 @@ interface IProps {
|
|||||||
function Admin(props: PropsWithChildren<IProps>) {
|
function Admin(props: PropsWithChildren<IProps>) {
|
||||||
const [admin, setAdmin] = useState<boolean>(false);
|
const [admin, setAdmin] = useState<boolean>(false);
|
||||||
|
|
||||||
const setIsAdmin = () => {
|
|
||||||
if (!props.isDeviceAdmin && !props.isGatewayAdmin && !props.isTenantAdmin) {
|
|
||||||
setAdmin(SessionStore.isAdmin());
|
|
||||||
} else {
|
|
||||||
if (props.tenantId === undefined) {
|
|
||||||
throw new Error("No tenantId is given");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.isTenantAdmin) {
|
|
||||||
setAdmin(SessionStore.isAdmin() || SessionStore.isTenantAdmin(props.tenantId));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.isDeviceAdmin) {
|
|
||||||
setAdmin(SessionStore.isAdmin() || SessionStore.isTenantDeviceAdmin(props.tenantId));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.isGatewayAdmin) {
|
|
||||||
setAdmin(SessionStore.isAdmin() || SessionStore.isTenantGatewayAdmin(props.tenantId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const setIsAdmin = () => {
|
||||||
|
if (!props.isDeviceAdmin && !props.isGatewayAdmin && !props.isTenantAdmin) {
|
||||||
|
setAdmin(SessionStore.isAdmin());
|
||||||
|
} else {
|
||||||
|
if (props.tenantId === undefined) {
|
||||||
|
throw new Error("No tenantId is given");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.isTenantAdmin) {
|
||||||
|
setAdmin(SessionStore.isAdmin() || SessionStore.isTenantAdmin(props.tenantId));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.isDeviceAdmin) {
|
||||||
|
setAdmin(SessionStore.isAdmin() || SessionStore.isTenantDeviceAdmin(props.tenantId));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.isGatewayAdmin) {
|
||||||
|
setAdmin(SessionStore.isAdmin() || SessionStore.isTenantGatewayAdmin(props.tenantId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
SessionStore.on("change", setIsAdmin);
|
SessionStore.on("change", setIsAdmin);
|
||||||
setIsAdmin();
|
setIsAdmin();
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, useCallback } from "react";
|
||||||
|
|
||||||
import { Table } from "antd";
|
import { Table } from "antd";
|
||||||
import { ColumnsType } from "antd/es/table";
|
import { ColumnsType } from "antd/es/table";
|
||||||
@ -23,21 +23,24 @@ function DataTable(props: IProps) {
|
|||||||
const [rows, setRows] = useState<object[]>([]);
|
const [rows, setRows] = useState<object[]>([]);
|
||||||
const [loading, setLoading] = useState<boolean>(true);
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
|
|
||||||
const onChangePage = (page: number, pz?: number | void) => {
|
const onChangePage = useCallback(
|
||||||
setLoading(true);
|
(page: number, pz?: number | void) => {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
if (!pz) {
|
if (!pz) {
|
||||||
pz = pageSize;
|
pz = pageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
props.getPage(pz, (page - 1) * pz, (totalCount: number, rows: object[]) => {
|
props.getPage(pz, (page - 1) * pz, (totalCount: number, rows: object[]) => {
|
||||||
setCurrentPage(page);
|
setCurrentPage(page);
|
||||||
setTotalCount(totalCount);
|
setTotalCount(totalCount);
|
||||||
setRows(rows);
|
setRows(rows);
|
||||||
setPageSize(pz || 0);
|
setPageSize(pz || 0);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
});
|
});
|
||||||
};
|
},
|
||||||
|
[props, pageSize],
|
||||||
|
);
|
||||||
|
|
||||||
const onShowSizeChange = (page: number, pageSize: number) => {
|
const onShowSizeChange = (page: number, pageSize: number) => {
|
||||||
onChangePage(page, pageSize);
|
onChangePage(page, pageSize);
|
||||||
@ -53,7 +56,7 @@ function DataTable(props: IProps) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onChangePage(currentPage, pageSize);
|
onChangePage(currentPage, pageSize);
|
||||||
}, [props, currentPage, pageSize]);
|
}, [props, currentPage, pageSize, onChangePage]);
|
||||||
|
|
||||||
const { getPage, refreshKey, ...otherProps } = props;
|
const { getPage, refreshKey, ...otherProps } = props;
|
||||||
let loadingProps = undefined;
|
let loadingProps = undefined;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, useCallback } from "react";
|
||||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { Menu, MenuProps, Typography } from "antd";
|
import { Menu, MenuProps, Typography } from "antd";
|
||||||
@ -67,7 +67,7 @@ function SideMenu() {
|
|||||||
navigate(`/tenants/${value}`);
|
navigate(`/tenants/${value}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseLocation = () => {
|
const parseLocation = useCallback(() => {
|
||||||
const path = location.pathname;
|
const path = location.pathname;
|
||||||
const tenantRe = /\/tenants\/([\w-]{36})/g;
|
const tenantRe = /\/tenants\/([\w-]{36})/g;
|
||||||
const match = tenantRe.exec(path);
|
const match = tenantRe.exec(path);
|
||||||
@ -134,7 +134,7 @@ function SideMenu() {
|
|||||||
if (/\/tenants\/[\w-]{36}\/applications.*/g.exec(path)) {
|
if (/\/tenants\/[\w-]{36}\/applications.*/g.exec(path)) {
|
||||||
setSelectedKey("tenant-applications");
|
setSelectedKey("tenant-applications");
|
||||||
}
|
}
|
||||||
};
|
}, [location.pathname, tenantId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
SessionStore.on("tenant.change", setTenant);
|
SessionStore.on("tenant.change", setTenant);
|
||||||
@ -150,11 +150,11 @@ function SideMenu() {
|
|||||||
return () => {
|
return () => {
|
||||||
SessionStore.removeListener("tenant.change", setTenant);
|
SessionStore.removeListener("tenant.change", setTenant);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [parseLocation]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
parseLocation();
|
parseLocation();
|
||||||
}, [location]);
|
}, [location, parseLocation]);
|
||||||
|
|
||||||
let items: MenuProps["items"] = [];
|
let items: MenuProps["items"] = [];
|
||||||
|
|
||||||
|
@ -26,6 +26,16 @@ function ApplicationLoader(props: IProps) {
|
|||||||
const [measurementKeys, setMeasurementKeys] = useState<string[]>([]);
|
const [measurementKeys, setMeasurementKeys] = useState<string[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const loadApplication = () => {
|
||||||
|
let req = new GetApplicationRequest();
|
||||||
|
req.setId(applicationId!);
|
||||||
|
|
||||||
|
ApplicationStore.get(req, (resp: GetApplicationResponse) => {
|
||||||
|
setApplication(resp.getApplication());
|
||||||
|
setMeasurementKeys(resp.getMeasurementKeysList());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
ApplicationStore.on("change", loadApplication);
|
ApplicationStore.on("change", loadApplication);
|
||||||
loadApplication();
|
loadApplication();
|
||||||
|
|
||||||
@ -34,16 +44,6 @@ function ApplicationLoader(props: IProps) {
|
|||||||
};
|
};
|
||||||
}, [applicationId]);
|
}, [applicationId]);
|
||||||
|
|
||||||
const loadApplication = () => {
|
|
||||||
let req = new GetApplicationRequest();
|
|
||||||
req.setId(applicationId!);
|
|
||||||
|
|
||||||
ApplicationStore.get(req, (resp: GetApplicationResponse) => {
|
|
||||||
setApplication(resp.getApplication());
|
|
||||||
setMeasurementKeys(resp.getMeasurementKeysList());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const app = application;
|
const app = application;
|
||||||
if (!app) {
|
if (!app) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -32,111 +32,111 @@ function ListIntegrations(props: IProps) {
|
|||||||
const [available, setAvailable] = useState<any[]>([]);
|
const [available, setAvailable] = useState<any[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const loadIntegrations = () => {
|
||||||
|
let req = new ListIntegrationsRequest();
|
||||||
|
req.setApplicationId(props.application.getId());
|
||||||
|
|
||||||
|
ApplicationStore.listIntegrations(req, (resp: ListIntegrationsResponse) => {
|
||||||
|
let configured: any[] = [];
|
||||||
|
let available: any[] = [];
|
||||||
|
|
||||||
|
const includes = (integrations: IntegrationListItem[], kind: IntegrationKind) => {
|
||||||
|
for (let x of integrations) {
|
||||||
|
if (x.getKind() === kind) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// AWS SNS
|
||||||
|
if (includes(resp.getResultList(), IntegrationKind.AWS_SNS)) {
|
||||||
|
configured.push(<AwsSnsCard application={props.application} />);
|
||||||
|
} else {
|
||||||
|
available.push(<AwsSnsCard application={props.application} add />);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Azure Service-Bus
|
||||||
|
if (includes(resp.getResultList(), IntegrationKind.AZURE_SERVICE_BUS)) {
|
||||||
|
configured.push(<AzureServiceBusCard application={props.application} />);
|
||||||
|
} else {
|
||||||
|
available.push(<AzureServiceBusCard application={props.application} add />);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GCP Pub/Sub
|
||||||
|
if (includes(resp.getResultList(), IntegrationKind.GCP_PUB_SUB)) {
|
||||||
|
configured.push(<GcpPubSubCard application={props.application} />);
|
||||||
|
} else {
|
||||||
|
available.push(<GcpPubSubCard application={props.application} add />);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTP
|
||||||
|
if (includes(resp.getResultList(), IntegrationKind.HTTP)) {
|
||||||
|
configured.push(<HttpCard application={props.application} />);
|
||||||
|
} else {
|
||||||
|
available.push(<HttpCard application={props.application} add />);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IFTTT
|
||||||
|
if (includes(resp.getResultList(), IntegrationKind.IFTTT)) {
|
||||||
|
configured.push(<IftttCard application={props.application} />);
|
||||||
|
} else {
|
||||||
|
available.push(<IftttCard application={props.application} add />);
|
||||||
|
}
|
||||||
|
|
||||||
|
// InfluxDB
|
||||||
|
if (includes(resp.getResultList(), IntegrationKind.INFLUX_DB)) {
|
||||||
|
configured.push(<InfluxdbCard application={props.application} />);
|
||||||
|
} else {
|
||||||
|
available.push(<InfluxdbCard application={props.application} add />);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MQTT
|
||||||
|
if (includes(resp.getResultList(), IntegrationKind.MQTT_GLOBAL)) {
|
||||||
|
configured.push(<MqttCard application={props.application} />);
|
||||||
|
}
|
||||||
|
|
||||||
|
// myDevices
|
||||||
|
if (includes(resp.getResultList(), IntegrationKind.MY_DEVICES)) {
|
||||||
|
configured.push(<MyDevicesCard application={props.application} />);
|
||||||
|
} else {
|
||||||
|
available.push(<MyDevicesCard application={props.application} add />);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pilot Things
|
||||||
|
if (includes(resp.getResultList(), IntegrationKind.PILOT_THINGS)) {
|
||||||
|
configured.push(<PilotThingsCard application={props.application} />);
|
||||||
|
} else {
|
||||||
|
available.push(<PilotThingsCard application={props.application} add />);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Semtech LoRa Cloud
|
||||||
|
if (includes(resp.getResultList(), IntegrationKind.LORA_CLOUD)) {
|
||||||
|
configured.push(<LoRaCloudCard application={props.application} />);
|
||||||
|
} else {
|
||||||
|
available.push(<LoRaCloudCard application={props.application} add />);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ThingsBoard
|
||||||
|
if (includes(resp.getResultList(), IntegrationKind.THINGS_BOARD)) {
|
||||||
|
configured.push(<ThingsBoardCard application={props.application} />);
|
||||||
|
} else {
|
||||||
|
available.push(<ThingsBoardCard application={props.application} add />);
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfigured(configured);
|
||||||
|
setAvailable(available);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
ApplicationStore.on("integration.delete", loadIntegrations);
|
ApplicationStore.on("integration.delete", loadIntegrations);
|
||||||
loadIntegrations();
|
loadIntegrations();
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
ApplicationStore.removeAllListeners("integration.delete");
|
ApplicationStore.removeAllListeners("integration.delete");
|
||||||
};
|
};
|
||||||
}, []);
|
}, [props.application]);
|
||||||
|
|
||||||
const loadIntegrations = () => {
|
|
||||||
let req = new ListIntegrationsRequest();
|
|
||||||
req.setApplicationId(props.application.getId());
|
|
||||||
|
|
||||||
ApplicationStore.listIntegrations(req, (resp: ListIntegrationsResponse) => {
|
|
||||||
let configured: any[] = [];
|
|
||||||
let available: any[] = [];
|
|
||||||
|
|
||||||
const includes = (integrations: IntegrationListItem[], kind: IntegrationKind) => {
|
|
||||||
for (let x of integrations) {
|
|
||||||
if (x.getKind() === kind) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// AWS SNS
|
|
||||||
if (includes(resp.getResultList(), IntegrationKind.AWS_SNS)) {
|
|
||||||
configured.push(<AwsSnsCard application={props.application} />);
|
|
||||||
} else {
|
|
||||||
available.push(<AwsSnsCard application={props.application} add />);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Azure Service-Bus
|
|
||||||
if (includes(resp.getResultList(), IntegrationKind.AZURE_SERVICE_BUS)) {
|
|
||||||
configured.push(<AzureServiceBusCard application={props.application} />);
|
|
||||||
} else {
|
|
||||||
available.push(<AzureServiceBusCard application={props.application} add />);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GCP Pub/Sub
|
|
||||||
if (includes(resp.getResultList(), IntegrationKind.GCP_PUB_SUB)) {
|
|
||||||
configured.push(<GcpPubSubCard application={props.application} />);
|
|
||||||
} else {
|
|
||||||
available.push(<GcpPubSubCard application={props.application} add />);
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP
|
|
||||||
if (includes(resp.getResultList(), IntegrationKind.HTTP)) {
|
|
||||||
configured.push(<HttpCard application={props.application} />);
|
|
||||||
} else {
|
|
||||||
available.push(<HttpCard application={props.application} add />);
|
|
||||||
}
|
|
||||||
|
|
||||||
// IFTTT
|
|
||||||
if (includes(resp.getResultList(), IntegrationKind.IFTTT)) {
|
|
||||||
configured.push(<IftttCard application={props.application} />);
|
|
||||||
} else {
|
|
||||||
available.push(<IftttCard application={props.application} add />);
|
|
||||||
}
|
|
||||||
|
|
||||||
// InfluxDB
|
|
||||||
if (includes(resp.getResultList(), IntegrationKind.INFLUX_DB)) {
|
|
||||||
configured.push(<InfluxdbCard application={props.application} />);
|
|
||||||
} else {
|
|
||||||
available.push(<InfluxdbCard application={props.application} add />);
|
|
||||||
}
|
|
||||||
|
|
||||||
// MQTT
|
|
||||||
if (includes(resp.getResultList(), IntegrationKind.MQTT_GLOBAL)) {
|
|
||||||
configured.push(<MqttCard application={props.application} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
// myDevices
|
|
||||||
if (includes(resp.getResultList(), IntegrationKind.MY_DEVICES)) {
|
|
||||||
configured.push(<MyDevicesCard application={props.application} />);
|
|
||||||
} else {
|
|
||||||
available.push(<MyDevicesCard application={props.application} add />);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pilot Things
|
|
||||||
if (includes(resp.getResultList(), IntegrationKind.PILOT_THINGS)) {
|
|
||||||
configured.push(<PilotThingsCard application={props.application} />);
|
|
||||||
} else {
|
|
||||||
available.push(<PilotThingsCard application={props.application} add />);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Semtech LoRa Cloud
|
|
||||||
if (includes(resp.getResultList(), IntegrationKind.LORA_CLOUD)) {
|
|
||||||
configured.push(<LoRaCloudCard application={props.application} />);
|
|
||||||
} else {
|
|
||||||
available.push(<LoRaCloudCard application={props.application} add />);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ThingsBoard
|
|
||||||
if (includes(resp.getResultList(), IntegrationKind.THINGS_BOARD)) {
|
|
||||||
configured.push(<ThingsBoardCard application={props.application} />);
|
|
||||||
} else {
|
|
||||||
available.push(<ThingsBoardCard application={props.application} add />);
|
|
||||||
}
|
|
||||||
|
|
||||||
setConfigured(configured);
|
|
||||||
setAvailable(available);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row gutter={24}>
|
<Row gutter={24}>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, useCallback } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
@ -33,11 +33,50 @@ function DeviceDashboard(props: IProps) {
|
|||||||
const [deviceLinkMetrics, setDeviceLinkMetrics] = useState<GetDeviceLinkMetricsResponse | undefined>(undefined);
|
const [deviceLinkMetrics, setDeviceLinkMetrics] = useState<GetDeviceLinkMetricsResponse | undefined>(undefined);
|
||||||
const [deviceLinkMetricsLoaded, setDeviceLinkMetricsLoaded] = useState<boolean>(false);
|
const [deviceLinkMetricsLoaded, setDeviceLinkMetricsLoaded] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
const loadDeviceMetrics = useCallback(
|
||||||
loadMetrics();
|
(start: Date, end: Date, agg: Aggregation) => {
|
||||||
}, [props, metricsAggregation]);
|
let startPb = new Timestamp();
|
||||||
|
let endPb = new Timestamp();
|
||||||
|
|
||||||
const loadMetrics = () => {
|
startPb.fromDate(start);
|
||||||
|
endPb.fromDate(end);
|
||||||
|
|
||||||
|
let req = new GetDeviceMetricsRequest();
|
||||||
|
req.setDevEui(props.device.getDevEui());
|
||||||
|
req.setStart(startPb);
|
||||||
|
req.setEnd(endPb);
|
||||||
|
req.setAggregation(agg);
|
||||||
|
|
||||||
|
DeviceStore.getMetrics(req, (resp: GetDeviceMetricsResponse) => {
|
||||||
|
setDeviceMetrics(resp);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[props.device],
|
||||||
|
);
|
||||||
|
|
||||||
|
const loadLinkMetrics = useCallback(
|
||||||
|
(start: Date, end: Date, agg: Aggregation) => {
|
||||||
|
let startPb = new Timestamp();
|
||||||
|
let endPb = new Timestamp();
|
||||||
|
|
||||||
|
startPb.fromDate(start);
|
||||||
|
endPb.fromDate(end);
|
||||||
|
|
||||||
|
let req = new GetDeviceLinkMetricsRequest();
|
||||||
|
req.setDevEui(props.device.getDevEui());
|
||||||
|
req.setStart(startPb);
|
||||||
|
req.setEnd(endPb);
|
||||||
|
req.setAggregation(agg);
|
||||||
|
|
||||||
|
DeviceStore.getLinkMetrics(req, (resp: GetDeviceLinkMetricsResponse) => {
|
||||||
|
setDeviceLinkMetrics(resp);
|
||||||
|
setDeviceLinkMetricsLoaded(true);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[props.device],
|
||||||
|
);
|
||||||
|
|
||||||
|
const loadMetrics = useCallback(() => {
|
||||||
const agg = metricsAggregation;
|
const agg = metricsAggregation;
|
||||||
const end = moment();
|
const end = moment();
|
||||||
let start = moment();
|
let start = moment();
|
||||||
@ -53,44 +92,11 @@ function DeviceDashboard(props: IProps) {
|
|||||||
setDeviceLinkMetricsLoaded(false);
|
setDeviceLinkMetricsLoaded(false);
|
||||||
loadLinkMetrics(start.toDate(), end.toDate(), agg);
|
loadLinkMetrics(start.toDate(), end.toDate(), agg);
|
||||||
loadDeviceMetrics(start.toDate(), end.toDate(), agg);
|
loadDeviceMetrics(start.toDate(), end.toDate(), agg);
|
||||||
};
|
}, [loadLinkMetrics, loadDeviceMetrics, metricsAggregation]);
|
||||||
|
|
||||||
const loadDeviceMetrics = (start: Date, end: Date, agg: Aggregation) => {
|
useEffect(() => {
|
||||||
let startPb = new Timestamp();
|
loadMetrics();
|
||||||
let endPb = new Timestamp();
|
}, [props, metricsAggregation, loadMetrics]);
|
||||||
|
|
||||||
startPb.fromDate(start);
|
|
||||||
endPb.fromDate(end);
|
|
||||||
|
|
||||||
let req = new GetDeviceMetricsRequest();
|
|
||||||
req.setDevEui(props.device.getDevEui());
|
|
||||||
req.setStart(startPb);
|
|
||||||
req.setEnd(endPb);
|
|
||||||
req.setAggregation(agg);
|
|
||||||
|
|
||||||
DeviceStore.getMetrics(req, (resp: GetDeviceMetricsResponse) => {
|
|
||||||
setDeviceMetrics(resp);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const loadLinkMetrics = (start: Date, end: Date, agg: Aggregation) => {
|
|
||||||
let startPb = new Timestamp();
|
|
||||||
let endPb = new Timestamp();
|
|
||||||
|
|
||||||
startPb.fromDate(start);
|
|
||||||
endPb.fromDate(end);
|
|
||||||
|
|
||||||
let req = new GetDeviceLinkMetricsRequest();
|
|
||||||
req.setDevEui(props.device.getDevEui());
|
|
||||||
req.setStart(startPb);
|
|
||||||
req.setEnd(endPb);
|
|
||||||
req.setAggregation(agg);
|
|
||||||
|
|
||||||
DeviceStore.getLinkMetrics(req, (resp: GetDeviceLinkMetricsResponse) => {
|
|
||||||
setDeviceLinkMetrics(resp);
|
|
||||||
setDeviceLinkMetricsLoaded(true);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const onMetricsAggregationChange = (e: RadioChangeEvent) => {
|
const onMetricsAggregationChange = (e: RadioChangeEvent) => {
|
||||||
setMetricsAggregation(e.target.value);
|
setMetricsAggregation(e.target.value);
|
||||||
|
@ -46,6 +46,25 @@ function DeviceLayout(props: IProps) {
|
|||||||
const [lastSeenAt, setLastSeenAt] = useState<Date | undefined>(undefined);
|
const [lastSeenAt, setLastSeenAt] = useState<Date | undefined>(undefined);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const loadDevice = () => {
|
||||||
|
let req = new GetDeviceRequest();
|
||||||
|
req.setDevEui(devEui!);
|
||||||
|
|
||||||
|
DeviceStore.get(req, (resp: GetDeviceResponse) => {
|
||||||
|
setDevice(resp.getDevice());
|
||||||
|
|
||||||
|
if (resp.getLastSeenAt() !== undefined) {
|
||||||
|
setLastSeenAt(resp.getLastSeenAt()!.toDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
let req = new GetDeviceProfileRequest();
|
||||||
|
req.setId(resp.getDevice()!.getDeviceProfileId());
|
||||||
|
DeviceProfileStore.get(req, (resp: GetDeviceProfileResponse) => {
|
||||||
|
setDeviceProfile(resp.getDeviceProfile());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
DeviceStore.on("change", loadDevice);
|
DeviceStore.on("change", loadDevice);
|
||||||
loadDevice();
|
loadDevice();
|
||||||
|
|
||||||
@ -54,25 +73,6 @@ function DeviceLayout(props: IProps) {
|
|||||||
};
|
};
|
||||||
}, [devEui]);
|
}, [devEui]);
|
||||||
|
|
||||||
const loadDevice = () => {
|
|
||||||
let req = new GetDeviceRequest();
|
|
||||||
req.setDevEui(devEui!);
|
|
||||||
|
|
||||||
DeviceStore.get(req, (resp: GetDeviceResponse) => {
|
|
||||||
setDevice(resp.getDevice());
|
|
||||||
|
|
||||||
if (resp.getLastSeenAt() !== undefined) {
|
|
||||||
setLastSeenAt(resp.getLastSeenAt()!.toDate());
|
|
||||||
}
|
|
||||||
|
|
||||||
let req = new GetDeviceProfileRequest();
|
|
||||||
req.setId(resp.getDevice()!.getDeviceProfileId());
|
|
||||||
DeviceProfileStore.get(req, (resp: GetDeviceProfileResponse) => {
|
|
||||||
setDeviceProfile(resp.getDeviceProfile());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteDevice = () => {
|
const deleteDevice = () => {
|
||||||
let req = new DeleteDeviceRequest();
|
let req = new DeleteDeviceRequest();
|
||||||
req.setDevEui(devEui!);
|
req.setDevEui(devEui!);
|
||||||
|
@ -3,7 +3,7 @@ import React, { useState } from "react";
|
|||||||
import { Struct } from "google-protobuf/google/protobuf/struct_pb";
|
import { Struct } from "google-protobuf/google/protobuf/struct_pb";
|
||||||
|
|
||||||
import { Switch, notification } from "antd";
|
import { Switch, notification } from "antd";
|
||||||
import { Button, Tabs, Space, Card, Row, Form, Input, InputNumber, Checkbox, Popconfirm } from "antd";
|
import { Button, Tabs, Space, Card, Row, Form, Input, InputNumber, Popconfirm } from "antd";
|
||||||
import { ColumnsType } from "antd/es/table";
|
import { ColumnsType } from "antd/es/table";
|
||||||
import { RedoOutlined, DeleteOutlined } from "@ant-design/icons";
|
import { RedoOutlined, DeleteOutlined } from "@ant-design/icons";
|
||||||
import { Buffer } from "buffer";
|
import { Buffer } from "buffer";
|
||||||
|
@ -23,7 +23,7 @@ interface IProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function GatewayDashboard(props: IProps) {
|
function GatewayDashboard(props: IProps) {
|
||||||
const [metricsAggregation, setMetricsAggregation] = useState<Aggregation>(Aggregation.DAY);
|
const [metricsAggregation] = useState<Aggregation>(Aggregation.DAY);
|
||||||
const [gatewayMetrics, setGatewayMetrics] = useState<GetGatewayMetricsResponse | undefined>(undefined);
|
const [gatewayMetrics, setGatewayMetrics] = useState<GetGatewayMetricsResponse | undefined>(undefined);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, useCallback } from "react";
|
||||||
|
|
||||||
import { Form, Input, InputNumber, Row, Col, Button, Tabs, Space, Card } from "antd";
|
import { Form, Input, InputNumber, Row, Col, Button, Tabs, Space, Card } from "antd";
|
||||||
import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
|
import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
|
||||||
@ -24,6 +24,29 @@ function GatewayForm(props: IProps) {
|
|||||||
const [lonValue, setLonValue] = useState<number>(0);
|
const [lonValue, setLonValue] = useState<number>(0);
|
||||||
const [locationPending, setLocationPending] = useState<boolean>(false);
|
const [locationPending, setLocationPending] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const setLocationFields = useCallback(
|
||||||
|
(lat: number, lon: number) => {
|
||||||
|
form.setFieldsValue({
|
||||||
|
location: {
|
||||||
|
latitude: lat,
|
||||||
|
longitude: lon,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[form],
|
||||||
|
);
|
||||||
|
|
||||||
|
const getCurrentLocation = useCallback(() => {
|
||||||
|
setLocationPending(true);
|
||||||
|
|
||||||
|
LocationStore.getLocation((loc: [number, number]) => {
|
||||||
|
setLatValue(loc[0]);
|
||||||
|
setLonValue(loc[1]);
|
||||||
|
setLocationPending(false);
|
||||||
|
setLocationFields(loc[0], loc[1]);
|
||||||
|
});
|
||||||
|
}, [setLocationFields]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!props.update) {
|
if (!props.update) {
|
||||||
getCurrentLocation();
|
getCurrentLocation();
|
||||||
@ -34,18 +57,7 @@ function GatewayForm(props: IProps) {
|
|||||||
setLonValue(loc.getLongitude());
|
setLonValue(loc.getLongitude());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [props]);
|
}, [props, getCurrentLocation]);
|
||||||
|
|
||||||
const getCurrentLocation = () => {
|
|
||||||
setLocationPending(true);
|
|
||||||
|
|
||||||
LocationStore.getLocation((loc: [number, number]) => {
|
|
||||||
setLatValue(loc[0]);
|
|
||||||
setLonValue(loc[1]);
|
|
||||||
setLocationPending(false);
|
|
||||||
setLocationFields(loc[0], loc[1]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const onFinish = (values: Gateway.AsObject) => {
|
const onFinish = (values: Gateway.AsObject) => {
|
||||||
const v = Object.assign(props.initialValues.toObject(), values);
|
const v = Object.assign(props.initialValues.toObject(), values);
|
||||||
@ -79,15 +91,6 @@ function GatewayForm(props: IProps) {
|
|||||||
setLocationFields(loc.lat, loc.lng);
|
setLocationFields(loc.lat, loc.lng);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setLocationFields = (lat: number, lon: number) => {
|
|
||||||
form.setFieldsValue({
|
|
||||||
location: {
|
|
||||||
latitude: lat,
|
|
||||||
longitude: lon,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const location: [number, number] = [latValue, lonValue];
|
const location: [number, number] = [latValue, lonValue];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user