From 1ec3058d45b29aca8f349a9f9b4b4b1151c5d28b Mon Sep 17 00:00:00 2001 From: Carter Date: Thu, 8 May 2025 16:45:42 -0600 Subject: [PATCH] added support page --- src/common/SmartBreadcrumb.tsx | 19 ++- src/device/DeviceActions.tsx | 8 +- src/navigation/Router.tsx | 5 + src/pages/DeviceSupport.tsx | 303 +++++++++++++++++++++++++++++++++ 4 files changed, 333 insertions(+), 2 deletions(-) create mode 100644 src/pages/DeviceSupport.tsx diff --git a/src/common/SmartBreadcrumb.tsx b/src/common/SmartBreadcrumb.tsx index 4d2c176..c931b79 100644 --- a/src/common/SmartBreadcrumb.tsx +++ b/src/common/SmartBreadcrumb.tsx @@ -7,6 +7,7 @@ import { LinkProps, Skeleton, Theme, + Typography, useTheme } from "@mui/material"; import { Replay } from "@mui/icons-material"; @@ -57,6 +58,7 @@ interface Props { paddingTop?: number; paddingBottom?: number; prependPaths?: string[]; + } interface LinkRouterProps extends LinkProps { @@ -289,7 +291,7 @@ export default function SmartBreadcrumb(props: Props) { if (prependPaths) pathnames.splice(pathnames.length - 1, 0, ...prependPaths); - pathnames.forEach((_value: any, index: any) => { + pathnames.forEach((value: any, index: any) => { const lastPath = index === pathnames.length - 1; const to = `/${pathnames.slice(0, index + 1).join("/")}`; @@ -310,6 +312,21 @@ export default function SmartBreadcrumb(props: Props) { links.push(linkComponent(to, label, lastPath)); } + if (value === "support") { + links.push( + + Support + + } + className={classes.chip} + /> + ) + } + }); return links; }; diff --git a/src/device/DeviceActions.tsx b/src/device/DeviceActions.tsx index 152ba70..baf2c49 100644 --- a/src/device/DeviceActions.tsx +++ b/src/device/DeviceActions.tsx @@ -24,7 +24,8 @@ import { AccountCircle as ObjectUsersIcon, SupervisedUserCircle as ObjectTeamsIcon, Sync as SyncDeviceIcon, - Wifi as WifiIcon + Wifi as WifiIcon, + Visibility } from "@mui/icons-material"; import { Skeleton } from "@mui/material"; // import Datadog from "assets/external/datadog.png"; @@ -498,6 +499,11 @@ export default function DeviceActions(props: Props) { const buttons = () => { return ( + {user.allowedTo("provision") && + navigate("support", { state: {device: device} })}> + + + } {canWrite && user.allowedTo("provision") && } {/* {!isShareableLink(match.params.deviceID) && ( */} import("pages/DeviceHistory")); const DevicePage = lazy(() => import("pages/Device")); @@ -103,6 +104,10 @@ export default function Router() { path="/:deviceID" // "/settings/basic" element={} /> + } + /> } diff --git a/src/pages/DeviceSupport.tsx b/src/pages/DeviceSupport.tsx new file mode 100644 index 0000000..961cdaa --- /dev/null +++ b/src/pages/DeviceSupport.tsx @@ -0,0 +1,303 @@ +import { Box, Button, FormControl, Grid2 as Grid, MenuItem, Select, Tab, Tabs, TextField, Typography, useTheme } from "@mui/material"; +import PageContainer from "./PageContainer"; +import { pond } from "protobuf-ts/pond"; +import LogsDisplay from "common/LogsDisplay"; +import { useEffect, useState } from "react"; +import { useDeviceAPI, useSnackbar } from "hooks"; +import { useLocation, useParams } from "react-router-dom"; +import { Device } from "models"; +import { getContextKeys, getContextTypes } from "pbHelpers/Context"; +import SmartBreadcrumb from "common/SmartBreadcrumb"; + +interface TabPanelProps { + children?: React.ReactNode; + index: any; + value: any; +} + +function TabPanelMine(props: TabPanelProps) { + const { children, value, index, ...other } = props; + + return ( + + ); +} + +export default function DeviceSupport() { + const deviceID = +(useParams<{ deviceID: string }>()?.deviceID ?? "0"); + + const deviceAPI = useDeviceAPI() + const snackbar = useSnackbar() + const theme = useTheme() + + const { state } = useLocation(); + const [device, setDevice] = useState(state?.device ? Device.create(state.device) : Device.create()) + const [tabNumber, setTabNumber] = useState(0) + const [newCap, setNewCap] = useState(0); + const [datacap, setDatacap] = useState(); + const [isOver, setIsOver] = useState(undefined); + const [pauseCheck, setPauseCheck] = useState(undefined); + const [inputFirmware, setInputFirmware] = useState(""); + const [platform, setPlatform] = useState( + pond.DevicePlatform.DEVICE_PLATFORM_INVALID + ); + + useEffect(() => { + if (state?.device) return + deviceAPI.get(deviceID, undefined, getContextKeys(), getContextTypes()).then(resp => { + setDevice(Device.create(resp.data)) + }) + }, [deviceID, state?.device]) + + const handleChange = (_event: React.ChangeEvent<{}>, newValue: number) => { + setTabNumber(newValue); + }; + + const resetQuackCount = () => { + deviceAPI.resetQuackCount(device.id()).then(resp => console.log(resp)); + }; + + const resetQuackCountTx = () => { + deviceAPI.resetQuackCountTx(device.id()).then(resp => console.log(resp)); + }; + + const resetQuackCountTx1000 = () => { + deviceAPI.resetQuackCountTx1000(device.id()).then(resp => console.log(resp)); + }; + + const clearPending = () => { + deviceAPI.clearPending(device.id()).then(resp => { + console.log(resp); + }); + }; + + const setFirmwareVersion = (firmwareVersion: string) => { + let status = device.status; + status.firmwareVersion = firmwareVersion; + deviceAPI.updateStatus(device.id(), status).then(() => { + snackbar.info("Firmware version set to " + firmwareVersion); + }); + }; + + const updateDevicePlatform = (firmwareVersion: pond.DevicePlatform) => { + let settings = device.settings; + settings.platform = firmwareVersion; + deviceAPI.update(device.id(), settings).then(() => { + snackbar.info("Platform set to " + firmwareVersion.toString()); + }); + }; + + const getDatacap = () => { + deviceAPI.getDatacap(device.id()).then(resp => { + //console.log(resp); + setDatacap(resp.data.overlimit); + }); + }; + + const updateDatacap = () => { + deviceAPI.setDatacap(device.id(), newCap).then(resp => { + console.log(resp); + }); + }; + + const checkLimit = () => { + deviceAPI.isOverLimit(device.id()).then(resp => { + //console.log(resp); + setIsOver(resp.data); + }); + }; + + const checkIfPaused = () => { + deviceAPI.isPaused(device.id()).then(resp => { + //console.log(resp); + setPauseCheck(resp.data); + }); + }; + + const pauseDevice = () => { + deviceAPI.pause(device.id()).then(resp => { + console.log(resp); + }); + }; + + const resumeDevice = () => { + deviceAPI.resume(device.id()).then(resp => { + console.log(resp); + }); + }; + + return ( + + + + + + + + + + + + General Options: + + + + + + + + + + + + + + setInputFirmware(e.currentTarget.value)} + /> + + + + + + + + + + + + + + + OPI Cable Functions: + + + + + + + + + + + + + + + + setNewCap(+e.target.value)} + /> + + + + + + + + + + + {datacap && datacap / 1000 / 1000}Mb + + + + + + + + + {isOver === undefined ? "Click to Check" : isOver ? "Over Limit" : "Under Limit"} + + + + + + + + + + {pauseCheck === undefined ? "Click to Check" : pauseCheck ? "Paused" : "Running"} + + + + + + + + + + + + History Not imported yet + {/* */} + + + ) +} \ No newline at end of file