diff --git a/src/common/SmartBreadcrumb.tsx b/src/common/SmartBreadcrumb.tsx index 4d2c176..be1d0fe 100644 --- a/src/common/SmartBreadcrumb.tsx +++ b/src/common/SmartBreadcrumb.tsx @@ -7,11 +7,12 @@ import { LinkProps, Skeleton, Theme, + Typography, useTheme } from "@mui/material"; import { Replay } from "@mui/icons-material"; import { useMobile } from "hooks"; -import { ReactNode, useEffect, useRef } from "react"; +import { ReactNode } from "react"; import { useLocation } from "react-router"; import { Link as RouterLink } from "react-router-dom"; import { or } from "utils/types"; @@ -57,11 +58,13 @@ interface Props { paddingTop?: number; paddingBottom?: number; prependPaths?: string[]; + state?: any; } interface LinkRouterProps extends LinkProps { to: string; replace?: boolean; + state?: any; } const LinkRouter = (props: LinkRouterProps) => ; @@ -72,7 +75,7 @@ export default function SmartBreadcrumb(props: Props) { const location = useLocation(); const isMobile = useMobile(); const classes = useStyles(); - const { loading, reload } = props; + const { loading, reload, state } = props; const groupID = (): string => { let index = prependPaths?.indexOf("groups") @@ -289,7 +292,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 +313,21 @@ export default function SmartBreadcrumb(props: Props) { links.push(linkComponent(to, label, lastPath)); } + if (value === "support") { + links.push( + + Support + + } + className={classes.chip} + /> + ) + } + }); return links; }; @@ -324,6 +342,7 @@ export default function SmartBreadcrumb(props: Props) { color={lastPath ? "textPrimary" : "textSecondary"} variant="subtitle1" to={to} + state={state} sx={{ '&:hover': { color: getThemeType() === "dark" ? 'white' : "black" }}} className={classes.textOverflow}> {label} diff --git a/src/common/StatusSen5x.tsx b/src/common/StatusSen5x.tsx index 262f595..912f128 100644 --- a/src/common/StatusSen5x.tsx +++ b/src/common/StatusSen5x.tsx @@ -176,12 +176,12 @@ export default function StatusPlenum(props: Props) { > - {device.status.sen5x?.voc.toFixed(1)}% + V: {device.status.sen5x?.voc.toFixed(1)}% - {device.status.sen5x?.nox.toFixed(1)}% + N: {device.status.sen5x?.nox.toFixed(1)}% diff --git a/src/device/DeviceActions.tsx b/src/device/DeviceActions.tsx index 152ba70..8356b6a 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"; @@ -47,7 +48,7 @@ import { Component, Device, deviceScope, Interaction } from "models"; // import { isShareableLink } from "pbHelpers/Device"; import { pond } from "protobuf-ts/pond"; import { useGlobalState } from "providers"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; // import { useHistory, useRouteMatch } from "react-router"; import { isOffline } from "utils/environment"; import { or } from "utils/types"; @@ -71,6 +72,7 @@ import Connection from "./Connection"; import ComponentOrder from "component/ComponentOrder"; import ArcGISDeviceData from "./ArcGISDeviceData"; import UpgradeDevice from "./UpgradeDevice"; +import { DevicePageData } from "pages/Device"; const useStyles = makeStyles((_theme: Theme) => { // const isMobile = useMobile() @@ -169,6 +171,19 @@ export default function DeviceActions(props: Props) { isJsonDataDialogOpen: false }); + const [devicePageData, setDevicePageData] = useState(undefined); + + useEffect(() => { + let newPageData: DevicePageData = { + device: device, + components: components, + interactions: interactions, + preferences: preferences, + permissions: permissions, + } + setDevicePageData(newPageData) + }, [device, components, interactions, preferences, permissions]) + const openDialog = (target: keyof DialogState) => { let updatedDialogState = cloneDeep(dialogState); updatedDialogState[target] = true; @@ -495,9 +510,18 @@ export default function DeviceActions(props: Props) { ); }; + const showSupport = () => { + return user.allowedTo("provision") && !location.pathname.includes("support") + } + const buttons = () => { return ( + {showSupport() && + navigate("support", { state: {device: device, devicePageData: devicePageData }})}> + + + } {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/Device.tsx b/src/pages/Device.tsx index 702285e..911e9f0 100644 --- a/src/pages/Device.tsx +++ b/src/pages/Device.tsx @@ -22,6 +22,15 @@ import { or } from "utils"; import ComponentDiagnostics from "component/ComponentDiagnostics"; import DeviceWizard from "device/DeviceWizard"; +export interface DevicePageData { + device: Device; + components: Component[]; + interactions: Interaction[]; + permissions: pond.Permission[]; + preferences: pond.DevicePreferences; + // componentPreferences: Map +} + export default function DevicePage() { const deviceAPI = useDeviceAPI() const snackbar = useSnackbar() @@ -30,6 +39,7 @@ export default function DevicePage() { const groupID = useParams<{ groupID: string }>()?.groupID ?? ""; const { state } = useLocation(); const [{ as, team, user }] = useGlobalState() + // console.log(state) const [device, setDevice] = useState(state?.device ? Device.create(state.device) : Device.create()) const [loading, setLoading] = useState(false) const [permissions, setPermissions] = useState([]) @@ -51,11 +61,21 @@ export default function DevicePage() { const [addComponentManualDialogOpen, setAddComponentManualDialogOpen] = useState(false) + // const [devicePageData, setDevicePageData] = useState(pond.GetDevicePageDataResponse.create()) + const loadDevice = () => { - // console.log("load device page data") if (loading) return + if (state?.devicePageData) { + setDevice(Device.create(state.devicePageData.device)) + setComponents(state.devicePageData.components.map((comp: pond.Component) => Component.create(comp))) + setInteractions(state.devicePageData.interactions.map((inter: pond.Interaction) => Interaction.create(inter))) + setPreferences(state.devicePageData.preferences) + setPermissions(state.devicePageData.permissions) + return + } setLoading(true) deviceAPI.getPageData(deviceID, getContextKeys(), getContextTypes(), as).then(resp => { + // setDevicePageData(resp.data) let device = Device.any(resp.data.device) // console.log(resp.data.device) setDevice(device) @@ -418,19 +438,9 @@ export default function DevicePage() { - + - setAddComponentManualDialogOpen(false)} - /> - {user.hasFeature("developer") === true && - - }