From 2a020eb6e748e58374a599c5b0b22c1bb64df565 Mon Sep 17 00:00:00 2001 From: Carter Date: Wed, 18 Jun 2025 16:17:27 -0600 Subject: [PATCH 01/11] added login redirect --- package-lock.json | 72 ++++++++++++++++++++++++++++++++++----- package.json | 1 + src/navigation/Router.tsx | 14 ++++---- src/pages/Login.tsx | 53 ++++++++++++++++++++++++++++ src/user/UserMenu.tsx | 8 ++--- 5 files changed, 127 insertions(+), 21 deletions(-) create mode 100644 src/pages/Login.tsx diff --git a/package-lock.json b/package-lock.json index baf369d..65ae1cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "notistack": "^3.0.1", "openweathermap-ts": "^1.2.10", "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#master", + "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", "react-color": "^2.19.3", @@ -6374,10 +6375,11 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -6900,10 +6902,11 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7616,6 +7619,15 @@ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" }, + "node_modules/decode-uri-component": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", + "integrity": "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==", + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -8370,10 +8382,11 @@ } }, "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -8402,6 +8415,18 @@ "node": ">=8" } }, + "node_modules/filter-obj": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz", + "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -10923,6 +10948,23 @@ "node": ">=6" } }, + "node_modules/query-string": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.2.1.tgz", + "integrity": "sha512-3jTGGLRzlhu/1ws2zlr4Q+GVMLCQTLFOj8CMX5x44cdZG9FQE07x2mQhaNxaKVPNmIDu0mvJ/cEwtY7Pim7hqA==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.4.1", + "filter-obj": "^5.1.0", + "split-on-first": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -12300,6 +12342,18 @@ "resolved": "https://registry.npmjs.org/splaytree-ts/-/splaytree-ts-1.0.2.tgz", "integrity": "sha512-0kGecIZNIReCSiznK3uheYB8sbstLjCZLiwcQwbmLhgHJj2gz6OnSPkVzJQCMnmEz1BQ4gPK59ylhBoEWOhGNA==" }, + "node_modules/split-on-first": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz", + "integrity": "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", diff --git a/package.json b/package.json index 7f976d1..67d05d8 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "notistack": "^3.0.1", "openweathermap-ts": "^1.2.10", "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#master", + "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", "react-color": "^2.19.3", diff --git a/src/navigation/Router.tsx b/src/navigation/Router.tsx index 9ef6d2c..666f487 100644 --- a/src/navigation/Router.tsx +++ b/src/navigation/Router.tsx @@ -9,6 +9,7 @@ import { getWhitelabel } from "services/whiteLabel"; import Ventilation from "pages/VentEditor"; import { useGlobalState } from "providers"; import DeviceSupport from "pages/DeviceSupport"; +import Login from "pages/Login"; const DeviceHistory = lazy(() => import("pages/DeviceHistory")); const DevicePage = lazy(() => import("pages/Device")); @@ -283,12 +284,12 @@ export default function Router() { }; if (isLoading) return null; - if (!isAuthenticated) { - loginWithRedirect() - return ( - null - ) - } + // if (!isAuthenticated) { + // loginWithRedirect() + // return ( + // null + // ) + // } function ErrorFallback({ error }: { error: Error }) { return
Something went wrong: {error.stack}
; @@ -302,6 +303,7 @@ export default function Router() { {/* Redirects */} } /> + } /> {/* } /> */} {/* } /> */} } /> diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx new file mode 100644 index 0000000..0e5304a --- /dev/null +++ b/src/pages/Login.tsx @@ -0,0 +1,53 @@ +import { RedirectLoginOptions, useAuth0 } from "@auth0/auth0-react"; +// import { useAuth } from "hooks"; +import queryString from "query-string"; +import { useCallback, useEffect } from "react"; +import { useLocation } from "react-router"; +// import Loading from "./Loading"; +import LoadingScreen from "app/LoadingScreen"; + +interface Props { + prevPath?: string; +} + +export default function Login(props: Props) { + const { prevPath } = props; + const location = useLocation(); + const { loginWithRedirect } = useAuth0(); + + const setRouteBeforeLogin = useCallback((): Promise => { + return new Promise(function(resolve) { + localStorage.setItem("routeBeforeLogin", prevPath ? prevPath : "/"); + return resolve("success"); + }); + }, [prevPath]); + + useEffect(() => { + const options: RedirectLoginOptions = { + authorizationParams: {} // Initialize here + }; + console.log(location) + if (location && location.search) { + let parsed = queryString.parse(location.search); + + console.log(parsed.signup) + if (parsed.signup === "true") { + // if (options.authorizationParams) options.authorizationParams.screen_hint = "signup"; // 'signup' tells Auth0 to show the signup tab + options.authorizationParams!.screen_hint = "signup"; // 'signup' tells Auth0 to show the signup tab + console.log(options) + } + + if (parsed.email && parsed.email !== "") { + // if (options.authorizationParams) options.authorizationParams.login_hint = parsed.email.toString(); // prefill email + options.authorizationParams!.login_hint = parsed.email.toString(); // prefill email + } + } + + setRouteBeforeLogin().finally(() => { + loginWithRedirect(options); + }); + }, [location, loginWithRedirect, setRouteBeforeLogin]); + + // return ; + return ; +} diff --git a/src/user/UserMenu.tsx b/src/user/UserMenu.tsx index 825ba85..bfd1baf 100644 --- a/src/user/UserMenu.tsx +++ b/src/user/UserMenu.tsx @@ -14,7 +14,7 @@ import { useNavigate } from "react-router-dom"; import TeamDialog from "teams/TeamDialog"; import AccessObject from "./AccessObject"; import { useSnackbar, useUserAPI } from "hooks"; -import { useThemeMode } from "theme/AppThemeProvider"; +// import { useThemeMode } from "theme/AppThemeProvider"; const useStyles = makeStyles((theme: Theme) => ({ accessIcon: { @@ -76,7 +76,7 @@ const useStyles = makeStyles((theme: Theme) => ({ export default function UserMenu() { - const { toggleMode } = useThemeMode() + // const { toggleMode } = useThemeMode() const [{ user, team, as }, dispatch] = useGlobalState(); const { loginWithRedirect } = useAuth0(); const classes = useStyles(); @@ -163,10 +163,6 @@ export default function UserMenu() { )} - - {}} className={classes.rightIcon} aria-label="Toggle Theme"> - - ); }; From 179cbcf542f5c5f976bbabb7777d55bed06446ea Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 23 Jun 2025 10:07:17 -0600 Subject: [PATCH 02/11] default argument for page container spacing --- src/pages/PageContainer.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/PageContainer.tsx b/src/pages/PageContainer.tsx index 0c78ed6..524fbbf 100644 --- a/src/pages/PageContainer.tsx +++ b/src/pages/PageContainer.tsx @@ -1,7 +1,7 @@ import { Container, SxProps, Theme } from "@mui/material"; import { makeStyles } from "@mui/styles"; import classNames from "classnames"; -import { useMobile } from "hooks"; +// import { useMobile } from "hooks"; import { PropsWithChildren } from "react"; const useStyles = makeStyles((theme: Theme) => ({ @@ -44,11 +44,11 @@ interface Props extends PropsWithChildren{ export const PageContainer: React.FunctionComponent = (props: Props) => { const classes = useStyles(); - const isMobile = useMobile(); + // const isMobile = useMobile(); const { children, fullViewport, isCenterCenter, sx } = props; // let fullViewport = false // let isCenterCenter = false - const spacing = props.spacing; + const spacing = props.spacing ? props.spacing : 2; return ( Date: Mon, 23 Jun 2025 10:24:38 -0600 Subject: [PATCH 03/11] fixed side navigator prop error --- src/navigation/SideNavigator.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/navigation/SideNavigator.tsx b/src/navigation/SideNavigator.tsx index 591aa27..38a10cb 100644 --- a/src/navigation/SideNavigator.tsx +++ b/src/navigation/SideNavigator.tsx @@ -436,7 +436,7 @@ export default function SideNavigator(props: Props) { } - {isAg || isStreamline && + {(isAg || isStreamline) && } - } + } ) } From f900ba6c9d8dc2ec7a6ea28d5cdfd6a5dcc1dde8 Mon Sep 17 00:00:00 2001 From: Carter Date: Mon, 23 Jun 2025 12:17:02 -0600 Subject: [PATCH 04/11] turning imitation to false when sharing team from the team page --- src/teams/TeamActions.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/teams/TeamActions.tsx b/src/teams/TeamActions.tsx index 63b335e..f12f9dc 100644 --- a/src/teams/TeamActions.tsx +++ b/src/teams/TeamActions.tsx @@ -146,6 +146,7 @@ export default function TeamActions(props: Props) { permissions={permissions} isDialogOpen={openState.share} closeDialogCallback={() => setOpenState({ ...openState, share: false })} + useImitation={false} /> Date: Tue, 24 Jun 2025 11:16:44 -0600 Subject: [PATCH 05/11] fix open weather ci variable --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 67d05d8..ee5b194 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,10 @@ "build": "tsc -b && vite build", "lint": "eslint .", "preview": "vite preview", - "build:staging": "VITE_AUTH0_CLIENT_DOMAIN=adaptivestaging.us.auth0.com VITE_AUTH0_AUDIENCE=stagingapi.brandxtech.ca VITE_AUTH0_CLIENT_ID=3ib460VvLwdeyse5iUSQfxkVdQaUmphP VITE_APP_API_URL=https://stagingapi.brandxtech.ca/v1 VITE_APP_WS_URL=wss://stagingapi.brandxtech.ca/v1/live NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_STAGING} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP={OPEN_WEATHERMAP} vite build", - "build:development": "VITE_AUTH0_CLIENT_ID=dzJTpqIeMA4Rwk4xujtwPbAO3TY32bM1 VITE_AUTH0_AUDIENCE=bxt-dev.api.adaptiveagriculture.ca VITE_APP_API_URL=https://bxt-dev.api.adaptiveagriculture.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_DEVELOPMENT} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP={OPEN_WEATHERMAP} vite build", - "build:production": "VITE_AUTH0_CLIENT_ID=5pUCkl2SfogkWmM244UDcLEUOp8EFdHd VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=api.brandxtech.ca VITE_APP_API_URL=https://api.brandxtech.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_PRODUCTION} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP={OPEN_WEATHERMAP} vite build", - "build:streamline": "VITE_AUTH0_CLIENT_ID=HwUV0hHNdVvU96zuMBTAU8i7nFdwwgIX VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=streamline.api.adaptiveagriculture.ca VITE_APP_API_URL=https://streamline.api.adaptiveagriculture.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_PRODUCTION} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP={OPEN_WEATHERMAP} vite build", + "build:staging": "VITE_AUTH0_CLIENT_DOMAIN=adaptivestaging.us.auth0.com VITE_AUTH0_AUDIENCE=stagingapi.brandxtech.ca VITE_AUTH0_CLIENT_ID=3ib460VvLwdeyse5iUSQfxkVdQaUmphP VITE_APP_API_URL=https://stagingapi.brandxtech.ca/v1 VITE_APP_WS_URL=wss://stagingapi.brandxtech.ca/v1/live NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_STAGING} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP=${OPEN_WEATHERMAP} vite build", + "build:development": "VITE_AUTH0_CLIENT_ID=dzJTpqIeMA4Rwk4xujtwPbAO3TY32bM1 VITE_AUTH0_AUDIENCE=bxt-dev.api.adaptiveagriculture.ca VITE_APP_API_URL=https://bxt-dev.api.adaptiveagriculture.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_DEVELOPMENT} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP=${OPEN_WEATHERMAP} vite build", + "build:production": "VITE_AUTH0_CLIENT_ID=5pUCkl2SfogkWmM244UDcLEUOp8EFdHd VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=api.brandxtech.ca VITE_APP_API_URL=https://api.brandxtech.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_PRODUCTION} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP=${OPEN_WEATHERMAP} vite build", + "build:streamline": "VITE_AUTH0_CLIENT_ID=HwUV0hHNdVvU96zuMBTAU8i7nFdwwgIX VITE_AUTH0_CLIENT_DOMAIN=brandxtech.auth0.com VITE_AUTH0_AUDIENCE=streamline.api.adaptiveagriculture.ca VITE_APP_API_URL=https://streamline.api.adaptiveagriculture.ca/v1 NODE_OPTIONS=--max_old_space_size=4096 VITE_APP_GOOGLE_API_KEY=${GOOGLE_API_KEY} VITE_APP_STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY_PRODUCTION} VITE_MAPBOX_ACCESS_TOKEN=${MAPBOX_ACCESS_TOKEN} VITE_CNHI_CLIENT_ID=${CNHI_CLIENT_ID} VITE_CNHI_AUTHORIZE_URL=${CNHI_AUTHORIZE_URL} VITE_CNHI_REDIRECT_URI=${CNHI_REDIRECT_URI} VITE_CNHI_SCOPES=${CNHI_SCOPES} VITE_CNHI_CONNECTION=${CNHI_CONNECTION} VITE_CNHI_AUDIENCE=${CNHI_AUDIENCE} VITE_APP_IMAGE4IO_USERNAME=${IMAGE4IO_USERNAME} VITE_APP_IMAGE4IO_PASSWORD=${IMAGE4IO_PASSWORD} VITE_JD_CLIENT_ID=${JD_CLIENT_ID} VITE_JD_AUTHORIZE_URL=${JD_AUTHORIZE_URL} VITE_JD_REDIRECT_URI=${JD_REDIRECT_URI} VITE_JD_SCOPES=${JD_SCOPES} VITE_JD_STATE=${JD_STATE} VITE_OPEN_WEATHERMAP=${OPEN_WEATHERMAP} vite build", "build:offline": "npx env-cmd offline,whitelabel npm run build", "test": "vitest" }, From 15d2a6a690e794a07f0848e79a98c560ceb94269 Mon Sep 17 00:00:00 2001 From: Carter Date: Tue, 24 Jun 2025 16:46:59 -0600 Subject: [PATCH 06/11] moved login page logic into the auth file to redirect correctly before auth redirects because you're unauthenticated --- src/navigation/Router.tsx | 4 +- src/pages/Login.tsx | 53 -------------------- src/providers/auth.tsx | 102 ++++++++++++++++++++++++++++++-------- 3 files changed, 81 insertions(+), 78 deletions(-) delete mode 100644 src/pages/Login.tsx diff --git a/src/navigation/Router.tsx b/src/navigation/Router.tsx index 666f487..698a9ac 100644 --- a/src/navigation/Router.tsx +++ b/src/navigation/Router.tsx @@ -9,7 +9,6 @@ import { getWhitelabel } from "services/whiteLabel"; import Ventilation from "pages/VentEditor"; import { useGlobalState } from "providers"; import DeviceSupport from "pages/DeviceSupport"; -import Login from "pages/Login"; const DeviceHistory = lazy(() => import("pages/DeviceHistory")); const DevicePage = lazy(() => import("pages/Device")); @@ -54,7 +53,7 @@ export const appendToUrl = (appendage: number | string) => { export default function Router() { - const { isAuthenticated, loginWithRedirect, isLoading } = useAuth0(); + const { isLoading } = useAuth0(); const whiteLabel = getWhitelabel(); const [{ user }] = useGlobalState(); @@ -303,7 +302,6 @@ export default function Router() { {/* Redirects */} } /> - } /> {/* } /> */} {/* } /> */} } /> diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx deleted file mode 100644 index 0e5304a..0000000 --- a/src/pages/Login.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { RedirectLoginOptions, useAuth0 } from "@auth0/auth0-react"; -// import { useAuth } from "hooks"; -import queryString from "query-string"; -import { useCallback, useEffect } from "react"; -import { useLocation } from "react-router"; -// import Loading from "./Loading"; -import LoadingScreen from "app/LoadingScreen"; - -interface Props { - prevPath?: string; -} - -export default function Login(props: Props) { - const { prevPath } = props; - const location = useLocation(); - const { loginWithRedirect } = useAuth0(); - - const setRouteBeforeLogin = useCallback((): Promise => { - return new Promise(function(resolve) { - localStorage.setItem("routeBeforeLogin", prevPath ? prevPath : "/"); - return resolve("success"); - }); - }, [prevPath]); - - useEffect(() => { - const options: RedirectLoginOptions = { - authorizationParams: {} // Initialize here - }; - console.log(location) - if (location && location.search) { - let parsed = queryString.parse(location.search); - - console.log(parsed.signup) - if (parsed.signup === "true") { - // if (options.authorizationParams) options.authorizationParams.screen_hint = "signup"; // 'signup' tells Auth0 to show the signup tab - options.authorizationParams!.screen_hint = "signup"; // 'signup' tells Auth0 to show the signup tab - console.log(options) - } - - if (parsed.email && parsed.email !== "") { - // if (options.authorizationParams) options.authorizationParams.login_hint = parsed.email.toString(); // prefill email - options.authorizationParams!.login_hint = parsed.email.toString(); // prefill email - } - } - - setRouteBeforeLogin().finally(() => { - loginWithRedirect(options); - }); - }, [location, loginWithRedirect, setRouteBeforeLogin]); - - // return ; - return ; -} diff --git a/src/providers/auth.tsx b/src/providers/auth.tsx index e66829a..c5ad0f7 100644 --- a/src/providers/auth.tsx +++ b/src/providers/auth.tsx @@ -1,31 +1,89 @@ -import { useAuth0 } from "@auth0/auth0-react"; -import { PropsWithChildren, useEffect } from "react"; +import { RedirectLoginOptions, useAuth0 } from "@auth0/auth0-react"; +import queryString from "query-string"; +import { PropsWithChildren, useCallback, useEffect } from "react"; +import { useLocation } from "react-router-dom"; interface Props extends PropsWithChildren{ setToken: React.Dispatch> + prevPath?: string } export default function AuthWrapper(props: Props) { - const { children, setToken } = props; - const { isLoading, loginWithRedirect, isAuthenticated, getAccessTokenSilently } = useAuth0(); - - useEffect(() => { - if (!isAuthenticated && !isLoading) { - loginWithRedirect(); - } - }, [isAuthenticated, loginWithRedirect, isLoading]); + const { children, setToken, prevPath } = props; + const { isLoading, loginWithRedirect, isAuthenticated, getAccessTokenSilently } = useAuth0(); - useEffect(() => { - if (isAuthenticated) getAccessTokenSilently().then(t => { - if (t.length < 1) { - loginWithRedirect() - } - setToken(t) - }).catch(() => { - // No token, go back to login - loginWithRedirect() - }) - }, [setToken, isAuthenticated]) - return children; + useEffect(() => { + const url = new URL(window.location.href); + + const isManualLoginPage = url.pathname === "/login"; + + if (isManualLoginPage) { + const options: RedirectLoginOptions = { + authorizationParams: {} // Initialize here + }; + + let parsed = queryString.parse(url.search); + if (parsed.signup === "true") { + options.authorizationParams!.screen_hint = "signup"; + } + + if (parsed.email && parsed.email !== "") { + options.authorizationParams!.login_hint = parsed.email.toString(); // prefill email + } + + loginWithRedirect(options) + + } else if (!isAuthenticated && !isLoading) { + loginWithRedirect(); + } + }, [isAuthenticated, loginWithRedirect, isLoading]); + + useEffect(() => { + if (isAuthenticated) getAccessTokenSilently().then(t => { + if (t.length < 1) { + loginWithRedirect() + } + console.log("setting token :)") + setToken(t) + }).catch(() => { + // No token, go back to login + loginWithRedirect() + }) + }, [setToken, isAuthenticated]) + + // const setRouteBeforeLogin = useCallback((): Promise => { + // return new Promise(function(resolve) { + // localStorage.setItem("routeBeforeLogin", prevPath ? prevPath : "/"); + // return resolve("success"); + // }); + // }, [prevPath]); + + useEffect(() => { + const options: RedirectLoginOptions = { + authorizationParams: {} // Initialize here + }; + console.log(location) + if (location && location.search) { + let parsed = queryString.parse(location.search); + + console.log(parsed.signup) + if (parsed.signup === "true") { + // if (options.authorizationParams) options.authorizationParams.screen_hint = "signup"; // 'signup' tells Auth0 to show the signup tab + options.authorizationParams!.screen_hint = "signup"; // 'signup' tells Auth0 to show the signup tab + console.log(options) + } + + if (parsed.email && parsed.email !== "") { + // if (options.authorizationParams) options.authorizationParams.login_hint = parsed.email.toString(); // prefill email + options.authorizationParams!.login_hint = parsed.email.toString(); // prefill email + } + } + + // setRouteBeforeLogin().finally(() => { + // loginWithRedirect(options); + // }); + }, [location, loginWithRedirect, /*setRouteBeforeLogin*/]); + + return children; } \ No newline at end of file From c7848a25ef1d5e3ceab1e942d596d66fb41bf75f Mon Sep 17 00:00:00 2001 From: Carter Date: Wed, 25 Jun 2025 09:45:02 -0600 Subject: [PATCH 07/11] put the login page back --- src/navigation/Router.tsx | 4 ++- src/pages/Login.tsx | 51 +++++++++++++++++++++++++++++++++++++++ src/providers/auth.tsx | 44 ++++----------------------------- src/user/UserMenu.tsx | 3 +-- 4 files changed, 60 insertions(+), 42 deletions(-) create mode 100644 src/pages/Login.tsx diff --git a/src/navigation/Router.tsx b/src/navigation/Router.tsx index 698a9ac..666f487 100644 --- a/src/navigation/Router.tsx +++ b/src/navigation/Router.tsx @@ -9,6 +9,7 @@ import { getWhitelabel } from "services/whiteLabel"; import Ventilation from "pages/VentEditor"; import { useGlobalState } from "providers"; import DeviceSupport from "pages/DeviceSupport"; +import Login from "pages/Login"; const DeviceHistory = lazy(() => import("pages/DeviceHistory")); const DevicePage = lazy(() => import("pages/Device")); @@ -53,7 +54,7 @@ export const appendToUrl = (appendage: number | string) => { export default function Router() { - const { isLoading } = useAuth0(); + const { isAuthenticated, loginWithRedirect, isLoading } = useAuth0(); const whiteLabel = getWhitelabel(); const [{ user }] = useGlobalState(); @@ -302,6 +303,7 @@ export default function Router() { {/* Redirects */} } /> + } /> {/* } /> */} {/* } /> */} } /> diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx new file mode 100644 index 0000000..661d1b9 --- /dev/null +++ b/src/pages/Login.tsx @@ -0,0 +1,51 @@ +import { RedirectLoginOptions, useAuth0 } from "@auth0/auth0-react"; +// import { useAuth } from "hooks"; +import queryString from "query-string"; +import { useCallback, useEffect } from "react"; +import { useLocation } from "react-router"; +// import Loading from "./Loading"; +import LoadingScreen from "app/LoadingScreen"; + +interface Props { + prevPath?: string; +} + +export default function Login(props: Props) { + const { prevPath } = props; + const location = useLocation(); + const { loginWithRedirect } = useAuth0(); + + const setRouteBeforeLogin = useCallback((): Promise => { + return new Promise(function(resolve) { + localStorage.setItem("routeBeforeLogin", prevPath ? prevPath : "/"); + return resolve("success"); + }); + }, [prevPath]); + + useEffect(() => { + const options: RedirectLoginOptions = { + authorizationParams: {} // Initialize here + }; + + if (location && location.search) { + let parsed = queryString.parse(location.search); + + if (parsed.signup === "true") { + // if (options.authorizationParams) options.authorizationParams.screen_hint = "signup"; // 'signup' tells Auth0 to show the signup tab + options.authorizationParams!.screen_hint = "signup"; // 'signup' tells Auth0 to show the signup tab + } + + if (parsed.email && parsed.email !== "") { + // if (options.authorizationParams) options.authorizationParams.login_hint = parsed.email.toString(); // prefill email + options.authorizationParams!.login_hint = parsed.email.toString(); // prefill email + } + } + + setRouteBeforeLogin().finally(() => { + loginWithRedirect(options); + }); + }, [location, loginWithRedirect, setRouteBeforeLogin]); + + // return ; + return ; +} diff --git a/src/providers/auth.tsx b/src/providers/auth.tsx index c5ad0f7..2c412f8 100644 --- a/src/providers/auth.tsx +++ b/src/providers/auth.tsx @@ -1,7 +1,6 @@ import { RedirectLoginOptions, useAuth0 } from "@auth0/auth0-react"; import queryString from "query-string"; -import { PropsWithChildren, useCallback, useEffect } from "react"; -import { useLocation } from "react-router-dom"; +import { PropsWithChildren, useEffect } from "react"; interface Props extends PropsWithChildren{ setToken: React.Dispatch> @@ -9,7 +8,7 @@ interface Props extends PropsWithChildren{ } export default function AuthWrapper(props: Props) { - const { children, setToken, prevPath } = props; + const { children, setToken } = props; const { isLoading, loginWithRedirect, isAuthenticated, getAccessTokenSilently } = useAuth0(); @@ -17,6 +16,7 @@ export default function AuthWrapper(props: Props) { const url = new URL(window.location.href); const isManualLoginPage = url.pathname === "/login"; + console.log(isManualLoginPage) if (isManualLoginPage) { const options: RedirectLoginOptions = { @@ -31,9 +31,9 @@ export default function AuthWrapper(props: Props) { if (parsed.email && parsed.email !== "") { options.authorizationParams!.login_hint = parsed.email.toString(); // prefill email } - + console.log(options) loginWithRedirect(options) - + } else if (!isAuthenticated && !isLoading) { loginWithRedirect(); } @@ -44,7 +44,6 @@ export default function AuthWrapper(props: Props) { if (t.length < 1) { loginWithRedirect() } - console.log("setting token :)") setToken(t) }).catch(() => { // No token, go back to login @@ -52,38 +51,5 @@ export default function AuthWrapper(props: Props) { }) }, [setToken, isAuthenticated]) - // const setRouteBeforeLogin = useCallback((): Promise => { - // return new Promise(function(resolve) { - // localStorage.setItem("routeBeforeLogin", prevPath ? prevPath : "/"); - // return resolve("success"); - // }); - // }, [prevPath]); - - useEffect(() => { - const options: RedirectLoginOptions = { - authorizationParams: {} // Initialize here - }; - console.log(location) - if (location && location.search) { - let parsed = queryString.parse(location.search); - - console.log(parsed.signup) - if (parsed.signup === "true") { - // if (options.authorizationParams) options.authorizationParams.screen_hint = "signup"; // 'signup' tells Auth0 to show the signup tab - options.authorizationParams!.screen_hint = "signup"; // 'signup' tells Auth0 to show the signup tab - console.log(options) - } - - if (parsed.email && parsed.email !== "") { - // if (options.authorizationParams) options.authorizationParams.login_hint = parsed.email.toString(); // prefill email - options.authorizationParams!.login_hint = parsed.email.toString(); // prefill email - } - } - - // setRouteBeforeLogin().finally(() => { - // loginWithRedirect(options); - // }); - }, [location, loginWithRedirect, /*setRouteBeforeLogin*/]); - return children; } \ No newline at end of file diff --git a/src/user/UserMenu.tsx b/src/user/UserMenu.tsx index bfd1baf..2b41a6f 100644 --- a/src/user/UserMenu.tsx +++ b/src/user/UserMenu.tsx @@ -1,11 +1,10 @@ -import { Avatar, Box, Button, Checkbox, Divider, IconButton, ListItemIcon, ListItemText, Menu, MenuItem, PaletteColor, Theme, Tooltip, useTheme } from "@mui/material"; +import { Avatar, Box, Button, Checkbox, Divider, ListItemIcon, ListItemText, Menu, MenuItem, PaletteColor, Theme, Tooltip, useTheme } from "@mui/material"; import { useGlobalState } from "../providers/StateContainer"; import { getSecondaryColour, getSignatureAccentColour } from "../services/whiteLabel"; import { makeStyles } from "@mui/styles"; import { LockOpen, Person, Lock, Settings, SupervisedUserCircle as TeamIcon, ExitToApp, PersonAdd } from "@mui/icons-material"; import { useState } from "react"; import UserTeamName from "./UserTeamName"; -import ThemeIcon from "../common/ThemeIcon"; import { useAuth0 } from "@auth0/auth0-react"; import UserSettings from "./UserSettings"; import UserAvatar from "./UserAvatar"; From 338b256d13fb8c8e1a50b38fea33e7566c1491d2 Mon Sep 17 00:00:00 2001 From: Carter Date: Wed, 25 Jun 2025 10:59:20 -0600 Subject: [PATCH 08/11] took out the login page route again, auth redirect forces login page if doing a sign up --- src/navigation/Router.tsx | 3 +-- src/pages/Login.tsx | 34 ++++++++++++++++++---------------- src/providers/auth.tsx | 6 ++++-- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/navigation/Router.tsx b/src/navigation/Router.tsx index 666f487..0a1ece9 100644 --- a/src/navigation/Router.tsx +++ b/src/navigation/Router.tsx @@ -9,7 +9,6 @@ import { getWhitelabel } from "services/whiteLabel"; import Ventilation from "pages/VentEditor"; import { useGlobalState } from "providers"; import DeviceSupport from "pages/DeviceSupport"; -import Login from "pages/Login"; const DeviceHistory = lazy(() => import("pages/DeviceHistory")); const DevicePage = lazy(() => import("pages/Device")); @@ -303,7 +302,7 @@ export default function Router() { {/* Redirects */} } /> - } /> + {/* } /> */} {/* } /> */} {/* } /> */} } /> diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 661d1b9..3dc7d2f 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -1,26 +1,26 @@ import { RedirectLoginOptions, useAuth0 } from "@auth0/auth0-react"; // import { useAuth } from "hooks"; import queryString from "query-string"; -import { useCallback, useEffect } from "react"; +import { useEffect } from "react"; import { useLocation } from "react-router"; // import Loading from "./Loading"; import LoadingScreen from "app/LoadingScreen"; -interface Props { - prevPath?: string; -} +// interface Props { +// prevPath?: string; +// } -export default function Login(props: Props) { - const { prevPath } = props; +export default function Login() { + // const { prevPath } = props; const location = useLocation(); const { loginWithRedirect } = useAuth0(); - const setRouteBeforeLogin = useCallback((): Promise => { - return new Promise(function(resolve) { - localStorage.setItem("routeBeforeLogin", prevPath ? prevPath : "/"); - return resolve("success"); - }); - }, [prevPath]); + // const setRouteBeforeLogin = useCallback((): Promise => { + // return new Promise(function(resolve) { + // localStorage.setItem("routeBeforeLogin", prevPath ? prevPath : "/"); + // return resolve("success"); + // }); + // }, [prevPath]); useEffect(() => { const options: RedirectLoginOptions = { @@ -33,6 +33,7 @@ export default function Login(props: Props) { if (parsed.signup === "true") { // if (options.authorizationParams) options.authorizationParams.screen_hint = "signup"; // 'signup' tells Auth0 to show the signup tab options.authorizationParams!.screen_hint = "signup"; // 'signup' tells Auth0 to show the signup tab + options.authorizationParams!.prompt = "login"; } if (parsed.email && parsed.email !== "") { @@ -41,10 +42,11 @@ export default function Login(props: Props) { } } - setRouteBeforeLogin().finally(() => { - loginWithRedirect(options); - }); - }, [location, loginWithRedirect, setRouteBeforeLogin]); + // setRouteBeforeLogin().finally(() => { + console.log(options.authorizationParams) + loginWithRedirect(options); + // }); + }, [location, loginWithRedirect]); // return ; return ; diff --git a/src/providers/auth.tsx b/src/providers/auth.tsx index 2c412f8..d07cf81 100644 --- a/src/providers/auth.tsx +++ b/src/providers/auth.tsx @@ -15,7 +15,8 @@ export default function AuthWrapper(props: Props) { useEffect(() => { const url = new URL(window.location.href); - const isManualLoginPage = url.pathname === "/login"; + const isManualLoginPage = url.pathname.includes("/login"); + console.log(url.pathname) console.log(isManualLoginPage) if (isManualLoginPage) { @@ -26,12 +27,13 @@ export default function AuthWrapper(props: Props) { let parsed = queryString.parse(url.search); if (parsed.signup === "true") { options.authorizationParams!.screen_hint = "signup"; + options.authorizationParams!.prompt = "login"; } if (parsed.email && parsed.email !== "") { options.authorizationParams!.login_hint = parsed.email.toString(); // prefill email } - console.log(options) + console.log(options.authorizationParams) loginWithRedirect(options) } else if (!isAuthenticated && !isLoading) { From d3314a1ab9839a3bff4c67c45d0e65a16916851e Mon Sep 17 00:00:00 2001 From: Carter Date: Wed, 25 Jun 2025 12:49:14 -0600 Subject: [PATCH 09/11] minor syntax clean --- src/navigation/Router.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/navigation/Router.tsx b/src/navigation/Router.tsx index 0a1ece9..29362ad 100644 --- a/src/navigation/Router.tsx +++ b/src/navigation/Router.tsx @@ -53,7 +53,7 @@ export const appendToUrl = (appendage: number | string) => { export default function Router() { - const { isAuthenticated, loginWithRedirect, isLoading } = useAuth0(); + const { /*isAuthenticated, loginWithRedirect,*/ isLoading } = useAuth0(); const whiteLabel = getWhitelabel(); const [{ user }] = useGlobalState(); From a43ff1a8ad83972799155032e3bb7fd7a93f9b62 Mon Sep 17 00:00:00 2001 From: Carter Date: Wed, 25 Jun 2025 13:44:40 -0600 Subject: [PATCH 10/11] added preferred units back to the user settings menu --- src/providers/auth.tsx | 4 +- src/user/UserSettings.tsx | 171 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 165 insertions(+), 10 deletions(-) diff --git a/src/providers/auth.tsx b/src/providers/auth.tsx index d07cf81..22ac76d 100644 --- a/src/providers/auth.tsx +++ b/src/providers/auth.tsx @@ -16,8 +16,6 @@ export default function AuthWrapper(props: Props) { const url = new URL(window.location.href); const isManualLoginPage = url.pathname.includes("/login"); - console.log(url.pathname) - console.log(isManualLoginPage) if (isManualLoginPage) { const options: RedirectLoginOptions = { @@ -33,7 +31,7 @@ export default function AuthWrapper(props: Props) { if (parsed.email && parsed.email !== "") { options.authorizationParams!.login_hint = parsed.email.toString(); // prefill email } - console.log(options.authorizationParams) + loginWithRedirect(options) } else if (!isAuthenticated && !isLoading) { diff --git a/src/user/UserSettings.tsx b/src/user/UserSettings.tsx index 32beec2..d8512d5 100644 --- a/src/user/UserSettings.tsx +++ b/src/user/UserSettings.tsx @@ -10,7 +10,7 @@ import { Textsms as TextIcon, Contrast, } from "@mui/icons-material"; -import { AppBar, Box, Button, Checkbox, CircularProgress, Collapse, Divider, FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel, Grid2, IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Radio, RadioGroup, TextField, Theme, ToggleButton, ToggleButtonGroup, Toolbar, Tooltip, Typography } from "@mui/material"; +import { AppBar, Box, Button, Checkbox, CircularProgress, Collapse, Divider, FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel, Grid2, IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText, MenuItem, Radio, RadioGroup, TextField, Theme, ToggleButton, ToggleButtonGroup, Toolbar, Tooltip, Typography } from "@mui/material"; import ResponsiveDialog from "common/ResponsiveDialog"; import UserAvatar from "./UserAvatar"; import { useGlobalState, useUserAPI } from "providers"; @@ -26,8 +26,10 @@ import moment from "moment"; import { IconPicker } from "common/IconPicker"; import { MuiTelInput } from "mui-tel-input"; import { useThemeMode } from "theme/AppThemeProvider"; -import ContractsIcon from "products/CommonIcons/contractIcon"; +// import ContractsIcon from "products/CommonIcons/contractIcon"; +import UnitsIcon from "@mui/icons-material/Category"; import { setThemeType } from "theme"; +import { IsAdaptiveAgriculture } from "services/whiteLabel"; const useStyles = makeStyles((theme: Theme) => { return ({ @@ -77,8 +79,9 @@ export default function UserSettings(props: Props) { const [profileExpanded, setProfileExpanded] = useState(false); const [avatarExpanded, setAvatarExpanded] = useState(false); const [notificationsExpanded, setNotificationsExpanded] = useState(false); + const [unitsExpanded, setUnitsExpanded] = useState(false); const [avatarUrl, setAvatarUrl] = useState(""); - const [themeValue, setThemeValue] = useState<"light" | "dark" | "system">(themeMode.mode) + // const [themeValue, setThemeValue] = useState<"light" | "dark" | "system">(themeMode.mode) useEffect(() => { function changeIcon(icon: string | undefined) { @@ -362,6 +365,160 @@ export default function UserSettings(props: Props) { setThemeType(theme) }; + const changePressureUnit = (value: any) => { + let updatedUser = User.clone(user); + let pressureUnit: pond.PressureUnit; + switch (value) { + case 1: + pressureUnit = pond.PressureUnit.PRESSURE_UNIT_KILOPASCALS; + break; + case 2: + pressureUnit = pond.PressureUnit.PRESSURE_UNIT_INCHES_OF_WATER; + break; + default: + pressureUnit = pond.PressureUnit.PRESSURE_UNIT_UNKNOWN; + break; + } + updatedUser.settings.pressureUnit = pressureUnit; + setUser(updatedUser); + }; + + const changeTemperatureUnit = (value: any) => { + let updatedUser = User.clone(user); + let temperatureUnit: pond.TemperatureUnit; + switch (value) { + case 1: + temperatureUnit = pond.TemperatureUnit.TEMPERATURE_UNIT_CELSIUS; + break; + case 2: + temperatureUnit = pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT; + break; + default: + temperatureUnit = pond.TemperatureUnit.TEMPERATURE_UNIT_UNKNOWN; + break; + } + updatedUser.settings.temperatureUnit = temperatureUnit; + setUser(updatedUser); + }; + + const changeDistanceUnit = (value: any) => { + let updatedUser = User.clone(user); + let distanceUnit: pond.DistanceUnit; + switch (value) { + case 1: + distanceUnit = pond.DistanceUnit.DISTANCE_UNIT_FEET; + break; + case 2: + distanceUnit = pond.DistanceUnit.DISTANCE_UNIT_METERS; + break; + default: + distanceUnit = pond.DistanceUnit.DISTANCE_UNIT_UNKNOWN; + break; + } + updatedUser.settings.distanceUnit = distanceUnit; + setUser(updatedUser); + }; + + const changeGrainUnit = (value: any) => { + let updatedUser = User.clone(user); + let grainUnit: pond.GrainUnit; + switch (value) { + case 1: + grainUnit = pond.GrainUnit.GRAIN_UNIT_BUSHELS; + break; + case 2: + grainUnit = pond.GrainUnit.GRAIN_UNIT_WEIGHT; + break; + default: + grainUnit = pond.GrainUnit.GRAIN_UNIT_UNKNOWN; + break; + } + updatedUser.settings.grainUnit = grainUnit; + setUser(updatedUser); + }; + + const unitPreferences = () => { + const { pressureUnit, temperatureUnit, distanceUnit, grainUnit } = user.settings; + return ( + + + changePressureUnit(event.target.value)} + margin="normal" + variant="outlined" + InputLabelProps={{ shrink: true }}> + + Kilopascals (kPa) + + + Inches of Water (iwg) + + + + + changeTemperatureUnit(event.target.value)} + margin="normal" + variant="outlined" + InputLabelProps={{ shrink: true }}> + Celsius (°C) + + Fahrenheit (°F) + + + + + changeDistanceUnit(event.target.value)} + margin="normal" + variant="outlined" + InputLabelProps={{ shrink: true }}> + Meters (m) + Feet (ft) + + + {IsAdaptiveAgriculture() && ( + + changeGrainUnit(event.target.value)} + margin="normal" + variant="outlined" + InputLabelProps={{ shrink: true }}> + Bushels (bu) + Tonnes (mT) + + + )} + + ); + }; + const themeToggle = () => { return ( - {/* + - setUnitsExpanded(!unitsExpanded)}> + setUnitsExpanded(!unitsExpanded)}> {unitsExpanded ? : } - + @@ -472,7 +629,7 @@ export default function UserSettings(props: Props) { - + {/* setMapsExpanded(!mapsExpanded)}> From 674763de2432dcb583bc4360a0b9ce38838efd16 Mon Sep 17 00:00:00 2001 From: Carter Date: Wed, 25 Jun 2025 14:10:02 -0600 Subject: [PATCH 11/11] saving preferred units on success --- src/user/UserSettings.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/user/UserSettings.tsx b/src/user/UserSettings.tsx index d8512d5..ec86924 100644 --- a/src/user/UserSettings.tsx +++ b/src/user/UserSettings.tsx @@ -13,7 +13,7 @@ import { import { AppBar, Box, Button, Checkbox, CircularProgress, Collapse, Divider, FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel, Grid2, IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText, MenuItem, Radio, RadioGroup, TextField, Theme, ToggleButton, ToggleButtonGroup, Toolbar, Tooltip, Typography } from "@mui/material"; import ResponsiveDialog from "common/ResponsiveDialog"; import UserAvatar from "./UserAvatar"; -import { useGlobalState, useUserAPI } from "providers"; +import { useGlobalState, useSnackbar, useUserAPI } from "providers"; import { useEffect, useState } from "react"; import { makeStyles } from "@mui/styles"; import { blue } from "@mui/material/colors"; @@ -30,6 +30,7 @@ import { useThemeMode } from "theme/AppThemeProvider"; import UnitsIcon from "@mui/icons-material/Category"; import { setThemeType } from "theme"; import { IsAdaptiveAgriculture } from "services/whiteLabel"; +import { setDistanceUnit, setGrainUnit, setPressureUnit, setTemperatureUnit } from "utils"; const useStyles = makeStyles((theme: Theme) => { return ({ @@ -73,6 +74,7 @@ export default function UserSettings(props: Props) { const [sharing, setSharing] = useState(false) const userAPI = useUserAPI(); const classes = useStyles() + const { success } = useSnackbar(); const [isLoading, setIsLoading] = useState(false); const [user, setUser] = useState(globalState.user); @@ -102,11 +104,11 @@ export default function UserSettings(props: Props) { .updateUser(user.id(), user.protobuf()) .then(() => { dispatch({ key: "user", value: user }); - // success("User settings successfully updated!"); - // setTemperatureUnit(user.settings.temperatureUnit); - // setPressureUnit(user.settings.pressureUnit); - // setDistanceUnit(user.settings.distanceUnit); - // setGrainUnit(user.settings.grainUnit); + success("User settings successfully updated!"); + setTemperatureUnit(user.settings.temperatureUnit); + setPressureUnit(user.settings.pressureUnit); + setDistanceUnit(user.settings.distanceUnit); + setGrainUnit(user.settings.grainUnit); }) .catch((error: any) => { error("Error occurred while updating your profile");