From 7130cce26b413407b7c9fba6bd8a77299ff7390a Mon Sep 17 00:00:00 2001 From: Carter Date: Wed, 7 May 2025 14:57:04 -0600 Subject: [PATCH 1/9] fixed teamlist not listing when using a team as context --- src/pages/Devices.tsx | 15 +++++++++++---- src/teams/TeamList.tsx | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/pages/Devices.tsx b/src/pages/Devices.tsx index 51374ee..c4239c5 100644 --- a/src/pages/Devices.tsx +++ b/src/pages/Devices.tsx @@ -57,7 +57,14 @@ const useStyles = makeStyles((theme: Theme) => { margin: theme.spacing(1), marginLeft: theme.spacing(2), display: "flex", - width: theme.spacing(26) + width: theme.spacing(32) + // justifyContent: "center", + }, + tagsCellContainer: { + margin: theme.spacing(1), + marginLeft: theme.spacing(2), + display: "flex", + width: theme.spacing(24) // justifyContent: "center", }, green: { @@ -328,8 +335,8 @@ export default function Devices() { - {description.length > 32 - ? description.substring(0, 32) + "..." + {description.length > 36 + ? description.substring(0, 36) + "..." : description} @@ -341,7 +348,7 @@ export default function Devices() { title: "Tags", render: (device: Device) => { return ( - + {device.status.tags.map((tag: pond.TagSettings) => ( diff --git a/src/teams/TeamList.tsx b/src/teams/TeamList.tsx index 021cfc2..6bb313f 100644 --- a/src/teams/TeamList.tsx +++ b/src/teams/TeamList.tsx @@ -80,7 +80,7 @@ export default function TeamList() { viewAs = undefined } teamAPI - .listTeams(limit, limit * page, undefined, "name", undefined, undefined, viewAs, search) + .listTeams(limit, limit * page, undefined, "name", undefined, undefined, " ", search) .then(resp => { setTotal(resp.data.total ? resp.data.total : 0); let newTeams: Team[] = [] From ddbfd4edc19b779158aa161cb2e4fcb7f524c50d Mon Sep 17 00:00:00 2001 From: Carter Date: Thu, 8 May 2025 09:41:07 -0600 Subject: [PATCH 2/9] fixed teamlist not listing when using a team as context in the select team menu --- src/teams/TeamSearch.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/teams/TeamSearch.tsx b/src/teams/TeamSearch.tsx index 1d64303..cf8ccc4 100644 --- a/src/teams/TeamSearch.tsx +++ b/src/teams/TeamSearch.tsx @@ -41,7 +41,7 @@ export default function TeamSearch(props: Props) { let options: Option[] = []; setLoading(true); teamAPI - .listTeams(10, 0, "desc", undefined, undefined, undefined, undefined, search) + .listTeams(10, 0, "desc", undefined, undefined, undefined, " ", search) .then(resp => { if (loadUsers) options.push({ From f1b18794b89e69ebc70c05728fb59a7dc91ee1cb Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 8 May 2025 13:18:49 -0600 Subject: [PATCH 3/9] updating the target in the config to fix the transpile error for mapbox --- vite.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/vite.config.ts b/vite.config.ts index 212bfe4..a657a38 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -22,6 +22,7 @@ export default defineConfig({ outDir: './build', sourcemap: true, minify: false, + target: 'esnext' }, esbuild: { keepNames: true, // Prevent function name mangling From 8ed5a44789d51f0309842ec263bd9035e1e5495a Mon Sep 17 00:00:00 2001 From: Carter Date: Thu, 8 May 2025 13:20:30 -0600 Subject: [PATCH 4/9] hotfix: changed loging with popup to login with redirect --- src/providers/http.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/providers/http.tsx b/src/providers/http.tsx index 6a77ad3..6811355 100644 --- a/src/providers/http.tsx +++ b/src/providers/http.tsx @@ -34,7 +34,7 @@ export const HTTPContext = createContext({} as IHTTPContext); export default function HTTPProvider(props: Props) { const { children, token } = props; - const { isAuthenticated, /*loginWithRedirect,*/ loginWithPopup } = useAuth0(); + const { isAuthenticated, loginWithRedirect } = useAuth0(); const defaultOptions = (demo: boolean = false) => { if (demo || !isAuthenticated || !token) { @@ -79,7 +79,7 @@ export default function HTTPProvider(props: Props) { function get(url: string, spreadOptions?: AxiosRequestConfig): Promise> { if (isTokenExpired(token)) { - loginWithPopup() + loginWithRedirect() } return axios.get(url, {...defaultOptions(), ...spreadOptions}); } From f316ec1c01f4176da9dd423ebf8107953a90be9c Mon Sep 17 00:00:00 2001 From: Carter Date: Thu, 8 May 2025 13:45:13 -0600 Subject: [PATCH 5/9] added the device upgrade code --- src/device/DeviceActions.tsx | 3 +- src/device/UpgradeDevice.tsx | 321 +++++++++++++++++++++++++++++++++++ src/models/Upgrade.ts | 32 ++++ src/models/index.ts | 2 +- src/pages/Firmware.tsx | 2 +- 5 files changed, 357 insertions(+), 3 deletions(-) create mode 100644 src/device/UpgradeDevice.tsx create mode 100644 src/models/Upgrade.ts diff --git a/src/device/DeviceActions.tsx b/src/device/DeviceActions.tsx index 787581c..152ba70 100644 --- a/src/device/DeviceActions.tsx +++ b/src/device/DeviceActions.tsx @@ -70,6 +70,7 @@ import SaveDeviceProfile from "./SaveDeviceProfile"; import Connection from "./Connection"; import ComponentOrder from "component/ComponentOrder"; import ArcGISDeviceData from "./ArcGISDeviceData"; +import UpgradeDevice from "./UpgradeDevice"; const useStyles = makeStyles((_theme: Theme) => { // const isMobile = useMobile() @@ -497,7 +498,7 @@ export default function DeviceActions(props: Props) { const buttons = () => { return ( - {/* {canWrite && user.allowedTo("provision") && } */} + {canWrite && user.allowedTo("provision") && } {/* {!isShareableLink(match.params.deviceID) && ( */} { + return ({ + dialogContent: { + marginTop: theme.spacing(2) + }, + buttonProgress: { + color: theme.palette.primary.main, + position: "absolute", + zIndex: 1 + }, + failed: { + color: theme.palette.error.main + } + }) +}); + +interface Props { + device: Device; +} + +export default function UpgradeDevice(props: Props) { + const classes = useStyles(); + const deviceAPI = useDeviceAPI(); + const { success, error } = useSnackbar(); + const firmwareAPI = useFirmwareAPI(); + const [{ firmware }] = useGlobalState(); + const prevFirmware = usePrevious(firmware); + const { device } = props; + const prevDevice = usePrevious(device); + const [open, setOpen] = useState(false); + const prevOpen = usePrevious(open); + const [upgrade, setUpgrade] = useState(Upgrade.create()); + const [gettingStatus, setGettingStatus] = useState(0); + + const progress = useCallback(() => { + return upgrade.status.progress; + }, [upgrade.status.progress]); + + const currentFirmware = () => { + return device.status.firmwareVersion; + }; + + const latestFirmware = () => { + return latestFirmwareVersion( + firmware, + device.settings.platform, + device.settings.upgradeChannel + ); + }; + + const upgradeVersion = () => { + return upgrade.settings.version; + }; + + const available = () => { + return currentFirmware() !== latestFirmware(); + }; + + const upgrading = useCallback(() => { + return progress() === "upgrading"; + }, [progress]); + + const completed = () => { + return progress() === "completed" && currentFirmware() === latestFirmware(); + }; + const failed = () => { + return progress() === "failed" && upgradeVersion() === latestFirmware(); + }; + + const percent = () => { + return Math.round((upgrade.status.offset / upgrade.status.size) * 100); + }; + + const tooltip = () => { + return upgrading() + ? "Upgrade in progress: " + percent() + "%" + : failed() + ? "Upgrade failed" + : "Upgrade Device"; + }; + + const upgradeTimingDesc = () => { + let desc = "requested " + moment(or(upgrade.status.started, 0)).fromNow(); + if (completed()) { + desc = "completed " + moment(or(upgrade.status.stopped, 0)).fromNow(); + } else if (failed()) { + desc = "failed " + moment(or(upgrade.status.changed, 0)).fromNow(); + } + + return desc; + }; + + const mode = () => { + let mode = "prompt"; + if (upgrading() || failed() || completed()) { + mode = "progress"; + } + return mode; + }; + + const getStatus = useCallback(() => { + if (gettingStatus === device.id() && !upgrading()) { + return; + } + setGettingStatus(device.id()); + deviceAPI + .getUpgradeStatus(device.id(), getContextKeys(), getContextTypes()) + .then((res: any) => { + if (res && res.data && res.data.upgrade) { + setUpgrade(Upgrade.any(res.data.upgrade)); + } + }) + .catch((err: any) => error(err)); + }, [device, deviceAPI, error, gettingStatus, upgrading]); + + useEffect(() => { + const deviceIdUnchanged = !prevDevice || prevDevice.id() === device.id(); + if ( + (open && !prevOpen) || + firmware !== prevFirmware || + (device !== prevDevice && deviceIdUnchanged) + ) { + getStatus(); + } + }, [open, prevOpen, getStatus, device, prevDevice, firmware, prevFirmware]); + + useEffect(() => { + function getStatusAgain() { + if (upgrading()) { + getStatus(); + } + } + const interval = setInterval(() => getStatusAgain(), 5000); + return () => { + clearInterval(interval); + }; + }, [open, getStatus, upgrading]); + + const close = () => { + setOpen(false); + }; + + const handleUpgrade = () => { + firmwareAPI + .upgradeFirmware(device.id()) + .then(() => { + success(device.name() + " will upgrade to " + latestFirmware() + " next time it checks in"); + getStatus(); + }) + .catch((err: any) => { + console.error(err); + error(err); + }); + }; + + const restart = () => { + firmwareAPI + .upgradeFirmware(device.id()) + .then(() => { + success( + "Upgrade successfully restarted, " + + device.name() + + " will upgrade next time it checks in" + ); + getStatus(); + }) + .catch((err: any) => { + console.error(err); + error(err); + }); + }; + + const cancel = () => { + firmwareAPI + .cancelUpgrade(device.id()) + .then(() => { + success("Upgrade cancelled"); + }) + .catch((err: any) => { + console.error(err); + error(err); + }); + }; + + const button = () => { + return ( + + setOpen(true)} + aria-label={tooltip()}> + + {upgrading() && ( + + )} + + + ); + }; + + return ( + + {(available() || upgrading() || failed()) && button()} + + {mode() === "prompt" && ( + + + Upgrade Device + + {device.name()} + + + + + + Upgrading from {currentFirmware()} to {latestFirmware()} +
+
+ It is recommended that the device be plugged in during the upgrade as it will take + several minutes to complete +
+
+ While the upgrade is in progress you can return to this dialog to view its status +
+
+ + + + +
+ )} + {mode() === "progress" && ( + + + Upgrading Device + + {device.name()} + + + + + + Upgrade to {latestFirmware()} {upgradeTimingDesc()} + +
+ + + {or(upgrade.status.offset, 0)} / {upgrade.status.size} bytes ({percent()}%) + + {failed() && ( + + +
+ Uh oh – something went wrong. You can try to{" "} + + restart + {" "} + the upgrade, if the problem persists we'll be alerted and follow up as soon as + possible. +
+
+ )} +
+ + + {upgrading() && ( + + )} + {failed() && ( + + )} + +
+ )} +
+
+ ); +} diff --git a/src/models/Upgrade.ts b/src/models/Upgrade.ts new file mode 100644 index 0000000..0802fd1 --- /dev/null +++ b/src/models/Upgrade.ts @@ -0,0 +1,32 @@ +import { pond } from "protobuf-ts/pond"; +import { or } from "utils/types"; +import { cloneDeep } from "lodash"; + +export class Upgrade { + public settings: pond.UpgradeSettings = pond.UpgradeSettings.create(); + public status: pond.UpgradeStatus = pond.UpgradeStatus.create(); + + public static create(pb?: pond.Upgrade): Upgrade { + let my = new Upgrade(); + if (pb) { + my.settings = pond.UpgradeSettings.fromObject(or(pb.settings, {})); + my.status = pond.UpgradeStatus.fromObject(or(pb.status, {})); + } + return my; + } + + public static any(data: any): Upgrade { + return Upgrade.create(pond.Upgrade.fromObject(cloneDeep(data))); + } + + public static clone(other: Upgrade): Upgrade { + let my = new Upgrade(); + my.settings = pond.UpgradeSettings.fromObject(cloneDeep(other.settings)); + my.status = pond.UpgradeStatus.fromObject(cloneDeep(other.status)); + return my; + } + + public key(): string { + return this.settings.key; + } +} diff --git a/src/models/index.ts b/src/models/index.ts index 08f0b54..8568628 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -11,7 +11,7 @@ export * from "./ShareableLink"; export * from "./Site"; export * from "./Tag"; export * from "./Task"; -// export * from "./Upgrade"; +export * from "./Upgrade"; // export * from "./User"; export * from "./user"; export * from "./Field"; diff --git a/src/pages/Firmware.tsx b/src/pages/Firmware.tsx index f6af40f..ecd628a 100644 --- a/src/pages/Firmware.tsx +++ b/src/pages/Firmware.tsx @@ -206,7 +206,7 @@ export default function Firmware() { // }; const load = useCallback(() => { - firmwareAPI.listFirmware(pageSize, pageSize * tablePage, "asc", "version", searchText) + firmwareAPI.listFirmware(pageSize, pageSize * tablePage, "desc", "version", searchText) .then((response) => { setTotal(response.data.total ? response.data.total : 0) let rows: FirmwareModel[] = or(response.data.firmware, []).map( From f06393ca62aa8226e26486e5463a8cbbe40a9a8e Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 8 May 2025 14:04:53 -0600 Subject: [PATCH 6/9] hotfix for bottom nav going to the wrong page --- src/navigation/BottomNavigator.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/navigation/BottomNavigator.tsx b/src/navigation/BottomNavigator.tsx index 514429a..9e36fe8 100644 --- a/src/navigation/BottomNavigator.tsx +++ b/src/navigation/BottomNavigator.tsx @@ -105,7 +105,7 @@ export default function BottomNavigator(props: Props) { return ( handleRouteChange(newValue)}> {isAdaptive && ( - } value="fields" /> + } value="visualFarm" /> )} {isAdaptive && ( } value="bins" /> @@ -114,7 +114,7 @@ export default function BottomNavigator(props: Props) { } - value="constructionsiteMap" + value="constructionMap" /> )} {isOmni && ( From 6d6c5c8a47bf72c4378fc98177e7ac29c283ca70 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 8 May 2025 14:14:57 -0600 Subject: [PATCH 7/9] stopped using tidy component in the use effect that ran the callback --- src/component/ComponentForm.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/component/ComponentForm.tsx b/src/component/ComponentForm.tsx index 7b7b406..ef61681 100644 --- a/src/component/ComponentForm.tsx +++ b/src/component/ComponentForm.tsx @@ -237,8 +237,7 @@ export default function ComponentForm(props: Props) { }; useEffect(() => { - let comp = tidyComponent(form.component); - componentChanged(comp, isFormValid()); + componentChanged(form.component, isFormValid()); }, [form.component, componentChanged]); // eslint-disable-line react-hooks/exhaustive-deps const isNameValid = (name: string): boolean => { @@ -950,7 +949,7 @@ export default function ComponentForm(props: Props) { Date: Thu, 8 May 2025 14:44:15 -0600 Subject: [PATCH 8/9] hotfix for open weather key in the gitlab ci --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 29a9969..c54c07b 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,9 @@ "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 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 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 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:offline": "npx env-cmd offline,whitelabel npm run build", "test": "vitest" }, From d5df3e870bc9d58aaacea545883dcdd00cfbf034 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Thu, 8 May 2025 15:17:21 -0600 Subject: [PATCH 9/9] re-implement a way to select start and end day --- src/common/time/TimeBar.tsx | 41 ++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/common/time/TimeBar.tsx b/src/common/time/TimeBar.tsx index 51fa212..73f6d3d 100644 --- a/src/common/time/TimeBar.tsx +++ b/src/common/time/TimeBar.tsx @@ -3,6 +3,7 @@ import { DialogActions, DialogContent, Grid, + TextField, Theme, Typography } from "@mui/material"; @@ -13,6 +14,7 @@ import ResponsiveDialog from "common/ResponsiveDialog"; import { DateRangePreset, GetDefaultDateRange, SetDefaultPreset } from "./DateRange"; import { useThemeType } from "hooks"; import { makeStyles } from "@mui/styles"; +import { cloneDeep } from "lodash"; interface Props { startDate: Moment; @@ -49,7 +51,7 @@ export default function TimeBar(props: Props) { const submitDateRange = () => { const startDate = dateRange[0] ? dateRange[0].clone() : moment(); - const endDate = dateRange[1] ? dateRange[1].clone() : moment(); + const endDate = dateRange[1] ? dateRange[1].add(1, "day").clone() : moment(); //add 1 day to the end time to include that day rather than have it be the cutoff updateDateRange(startDate, endDate, false); setDateRangeDialog(false); setActiveView("selectRange"); @@ -85,19 +87,30 @@ export default function TimeBar(props: Props) { onClose={() => setDateRangeDialog(false)} aria-labelledby="date-range-dialog"> - {/* setDateRange(date)} - renderInput={(startProps, endProps) => ( - - - to - - - )} - /> */} - DATE PICKER GOES HERE + { + let range = cloneDeep(dateRange) + range[0] = moment(e.target.value) + setDateRange(range) + }} + /> + { + let range = cloneDeep(dateRange) + range[1] = moment(e.target.value) + setDateRange(range) + }} + />