diff --git a/package.json b/package.json index d3863a1..efb9aa8 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" }, 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) + }} + /> + + + + )} + {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/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 && ( 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/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( 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}); } 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[] = [] 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({