diff --git a/index.html b/index.html index da05f1e..31b4ca1 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - Adaptive Dashboard + Adaptive Dashboard diff --git a/package.json b/package.json index efb9aa8..8e3ebd3 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "start": "VITE_AUTH0_CLIENT_ID=5pUCkl2SfogkWmM244UDcLEUOp8EFdHd VITE_AUTH0_AUDIENCE=api.brandxtech.ca VITE_APP_API_URL=https://api.brandxtech.ca/v1 VITE_APP_WS_URL=ws://api.brandxtech.ca/v1/live vite", "start-local": "VITE_AUTH0_CLIENT_ID=dzJTpqIeMA4Rwk4xujtwPbAO3TY32bM1 VITE_AUTH0_AUDIENCE=bxt-dev.api.adaptiveagriculture.ca VITE_APP_API_URL=http://localhost:50052/v1 VITE_APP_WS_URL=ws://localhost:50052/v1/live VITE_APP_BILLING_URL=http://localhost:50053/v1 VITE_APP_RECLUSE_URL=http://localhost:50054/v1 VITE_APP_GITLAB_URL=http://localhost:50055/v1 vite", "start-dev": "VITE_AUTH0_CLIENT_ID=dzJTpqIeMA4Rwk4xujtwPbAO3TY32bM1 VITE_APP_API_URL=https://bxt-dev.api.adaptiveagriculture.ca/v1 VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=bxt-dev.api.adaptiveagriculture.ca VITE_AUTH0_DEV_CLIENT_ID=dzJTpqIeMA4Rwk4xujtwPbAO3TY32bM1 vite", - "start-staging": "VITE_AUTH0_CLIENT_ID=3ib460VvLwdeyse5iUSQfxkVdQaUmphP VITE_AUTH0_AUDIENCE=stagingapi.brandxtech.ca VITE_AUTH0_CLIENT_DOMAIN=adaptivestaging.us.auth0.com VITE_APP_API_URL=https://stagingapi.brandxtech.ca/v1 VITE_APP_WS_URL=ws://stagingapi.brandxtech.ca/v1/live VITE_APP_AUTH0_CLIENT_DOMAIN=adaptivestaging.us.auth0.com VITE_APP_AUTH0_AUDIENCE=stagingapi.brandxtech.ca vite", + "start-staging": "VITE_LOCAL_STAGING=true VITE_AUTH0_CLIENT_ID=3ib460VvLwdeyse5iUSQfxkVdQaUmphP VITE_AUTH0_AUDIENCE=stagingapi.brandxtech.ca VITE_AUTH0_CLIENT_DOMAIN=adaptivestaging.us.auth0.com VITE_APP_API_URL=https://stagingapi.brandxtech.ca/v1 VITE_APP_WS_URL=ws://stagingapi.brandxtech.ca/v1/live VITE_APP_AUTH0_CLIENT_DOMAIN=adaptivestaging.us.auth0.com VITE_APP_AUTH0_AUDIENCE=stagingapi.brandxtech.ca vite", "build": "tsc -b && vite build", "lint": "eslint .", "preview": "vite preview", diff --git a/public/Staging/android-chrome-192x192.png b/public/Staging/android-chrome-192x192.png new file mode 100644 index 0000000..cbd70d4 Binary files /dev/null and b/public/Staging/android-chrome-192x192.png differ diff --git a/public/Staging/android-chrome-512x512.png b/public/Staging/android-chrome-512x512.png new file mode 100644 index 0000000..5d93e84 Binary files /dev/null and b/public/Staging/android-chrome-512x512.png differ diff --git a/public/Staging/apple-touch-icon.png b/public/Staging/apple-touch-icon.png new file mode 100644 index 0000000..0914e18 Binary files /dev/null and b/public/Staging/apple-touch-icon.png differ diff --git a/public/Staging/browserconfig.xml b/public/Staging/browserconfig.xml new file mode 100644 index 0000000..d416bc5 --- /dev/null +++ b/public/Staging/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #ffffff + + + diff --git a/public/Staging/favicon-16x16.png b/public/Staging/favicon-16x16.png new file mode 100644 index 0000000..aa87654 Binary files /dev/null and b/public/Staging/favicon-16x16.png differ diff --git a/public/Staging/favicon-32x32.png b/public/Staging/favicon-32x32.png new file mode 100644 index 0000000..a606ca0 Binary files /dev/null and b/public/Staging/favicon-32x32.png differ diff --git a/public/Staging/favicon.ico b/public/Staging/favicon.ico new file mode 100644 index 0000000..54725be Binary files /dev/null and b/public/Staging/favicon.ico differ diff --git a/public/Staging/manifest.json b/public/Staging/manifest.json new file mode 100644 index 0000000..aad40f6 --- /dev/null +++ b/public/Staging/manifest.json @@ -0,0 +1,26 @@ +{ + "name": "Brand X Technologies", + "short_name": "BXT", + "icons": [ + { + "src": "favicon.ico", + "sizes": "48x48", + "type": "image/x-icon" + }, + { + "src": "android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "start_url": "/", + "theme_color": "#272727", + "background_color": "#424242", + "display": "standalone", + "orientation": "any" +} diff --git a/public/Staging/mstile-150x150.png b/public/Staging/mstile-150x150.png new file mode 100644 index 0000000..e91210a Binary files /dev/null and b/public/Staging/mstile-150x150.png differ diff --git a/public/Staging/safari-pinned-tab.svg b/public/Staging/safari-pinned-tab.svg new file mode 100644 index 0000000..5f44534 --- /dev/null +++ b/public/Staging/safari-pinned-tab.svg @@ -0,0 +1,2198 @@ + + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/App.tsx b/src/app/App.tsx index 46e7121..16bb781 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -37,6 +37,11 @@ function App() { faviconDocument.href = "BrandXTechnologies/favicon.ico" }) + // Set title + const titleElement = document.getElementById("title-id") as HTMLElement; + if (titleElement) titleElement.textContent = whiteLabel.name; + + let domain: string | undefined = import.meta.env.VITE_AUTH0_CLIENT_DOMAIN; let audience: string | undefined = import.meta.env.VITE_AUTH0_AUDIENCE; diff --git a/src/common/ButtonGroup.tsx b/src/common/ButtonGroup.tsx index f23bc0a..f1d80f4 100644 --- a/src/common/ButtonGroup.tsx +++ b/src/common/ButtonGroup.tsx @@ -72,14 +72,14 @@ const useStyles = makeStyles((theme: Theme) => { marginLeft: theme.spacing(0.05), marginRight: theme.spacing(0.05), "&:hover": { - backgroundColor: getSecondaryColour(), //use the colour of the whitelabel - //backgroundColor: "gold", + //backgroundColor: getSecondaryColour(), //use the colour of the whitelabel + backgroundColor: "gold", //for now Dustin just wants it to be gold color: "black", } }, buttonToggled: { - backgroundColor: getSecondaryColour(), //use the colour of the whitelabel - //backgroundColor: "gold", + //backgroundColor: getSecondaryColour(), //use the colour of the whitelabel + backgroundColor: "gold", //for now Dustin just wants it to be gold color: "black", borderRadius: 24, fontWeight: "bold" 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 && - - }