From 6dbb7c3432feb97365a197a24de103aa0b979db9 Mon Sep 17 00:00:00 2001 From: csawatzky Date: Tue, 21 Oct 2025 10:40:14 -0600 Subject: [PATCH] temp commit so i can change branches --- package-lock.json | 4 +- package.json | 2 +- src/gate/GateList.tsx | 13 +- src/maps/MapBase.tsx | 3 +- .../mapObjectControllers/AgMapController.tsx | 172 ++++++++++-------- src/providers/pond/gateAPI.tsx | 22 ++- src/reports/MiPCA/GateReports.tsx | 31 +++- 7 files changed, 160 insertions(+), 87 deletions(-) diff --git a/package-lock.json b/package-lock.json index dda1c90..b9275ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,7 +42,7 @@ "mui-tel-input": "^7.0.0", "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", + "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#mipca_reports", "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", @@ -10911,7 +10911,7 @@ }, "node_modules/protobuf-ts": { "version": "1.0.0", - "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#d0ac088df3822c10c0497f49173d1679b4e107b0", + "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#4aa7c4efefa38e86c21ec08cddcbd7f789b38464", "dependencies": { "protobufjs": "^6.8.8" } diff --git a/package.json b/package.json index ee0e9b7..a8e73f7 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "mui-tel-input": "^7.0.0", "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", + "protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#mipca_reports", "query-string": "^9.2.1", "react": "^18.3.1", "react-beautiful-dnd": "^13.1.1", diff --git a/src/gate/GateList.tsx b/src/gate/GateList.tsx index 5c548e2..b590b2b 100644 --- a/src/gate/GateList.tsx +++ b/src/gate/GateList.tsx @@ -1,5 +1,5 @@ import { Gate } from "models/Gate"; -import { Box, Card, IconButton, List, ListItem, ListItemText, Theme, Typography } from "@mui/material"; +import { Box, Button, Card, IconButton, List, ListItem, ListItemText, Theme, Typography } from "@mui/material"; import React, { useCallback, useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import { useMobile } from "hooks"; @@ -13,6 +13,7 @@ import GateSettings from "./GateSettings"; import { useGateAPI, useGlobalState } from "providers"; import { Settings } from "@mui/icons-material"; import { cloneDeep } from "lodash"; +import GateReports from "reports/MiPCA/GateReports"; interface Props { //gates: Gate[]; @@ -54,6 +55,7 @@ export default function GateList(props: Props) { const [gates, setGates] = useState([]) const [selectedGate, setSelectedGate] = useState() const [search, setSearch] = useState("") + const [openReports, setOpenReports] = useState(false) const goToGate = (gate: Gate) => { let path = "/terminals/" + gate.key; @@ -208,6 +210,8 @@ export default function GateList(props: Props) { const gateTable = () => { return ( + actions={} + title="Terminal Gates" page={tablePage} pageSize={pageSize} columns={isMobile || props.useMobile ? mobileCols() : desktopCols()} @@ -237,7 +241,8 @@ export default function GateList(props: Props) { ) }; - return + return ( + {gateTable()} - + {setOpenReports(false)}}/> + + ) } diff --git a/src/maps/MapBase.tsx b/src/maps/MapBase.tsx index b1dc432..59689fc 100644 --- a/src/maps/MapBase.tsx +++ b/src/maps/MapBase.tsx @@ -241,7 +241,7 @@ export default function MapBase(props: Props) { homeMarkerAPI .listHomeMarkers(1, 0, undefined, undefined, undefined, undefined, as) .then(resp => { - if (resp.data.homeMarker.length < 1) { + if (resp.data.homeMarker === undefined) { setHomePin(undefined); setHaveHome(false); setStartingView(props.currentView); @@ -271,6 +271,7 @@ export default function MapBase(props: Props) { } }) .catch(err => { + console.log(err) openSnack("Could not load Home Pin"); }); }, [as, homeMarkerAPI, openSnack, props.ignoreHomeLoad, user]); // eslint-disable-line react-hooks/exhaustive-deps diff --git a/src/maps/mapObjectControllers/AgMapController.tsx b/src/maps/mapObjectControllers/AgMapController.tsx index 7001f1a..14817ee 100644 --- a/src/maps/mapObjectControllers/AgMapController.tsx +++ b/src/maps/mapObjectControllers/AgMapController.tsx @@ -221,24 +221,26 @@ import { Result } from "@mapbox/mapbox-gl-geocoder"; .then(resp => { let fields: Map = new Map(); let fieldEntries: Result[] = []; - resp.data.fields.forEach(f => { - let field = Field.any(f); - fields.set(field.key(), field); - fieldEntries.push({ - id: field.key(), - place_name: field.name(), - place_type: ["field"], - center: [field.center().longitude, field.center().latitude], - address: "", - type: "Feature", - text: field.name(), - bbox: [0,0,0,0], - geometry: {type: "Point", coordinates: [field.center().longitude, field.center().latitude]}, - context: [], - properties: {}, - relevance: 0 + if(resp.data.fields){ + resp.data.fields.forEach(f => { + let field = Field.any(f); + fields.set(field.key(), field); + fieldEntries.push({ + id: field.key(), + place_name: field.name(), + place_type: ["field"], + center: [field.center().longitude, field.center().latitude], + address: "", + type: "Feature", + text: field.name(), + bbox: [0,0,0,0], + geometry: {type: "Point", coordinates: [field.center().longitude, field.center().latitude]}, + context: [], + properties: {}, + relevance: 0 + }); }); - }); + } setFields(fields); setFieldSearchEntries(fieldEntries); }) @@ -314,53 +316,56 @@ import { Result } from "@mapbox/mapbox-gl-geocoder"; let bagOp: BagModel[] = []; let bagMarkerData: Map = new Map(); let bagEntries: Result[] = []; - resp.data.grainBags.forEach(bag => { - let b = BagModel.create(bag); - bags.set(b.key(), b); - if (bag.settings) { - if (!b.settings.startLocation?.longitude && !b.settings.endLocation?.longitude) { - bagOp.push(b); - } else { - //build the data for the marker - //TODO-CS: think about making the creation of marker data a function in the object model - let mData: MarkerData = { - title: b.name(), - longitude: b.centerLocation().longitude, - latitude: b.centerLocation().latitude, - visibleLevels: { max: 13 }, - colour: b.settings.theme?.color ?? "white", - clickFunc: (e, i, isMobile) => { - clickDelay(); - closeDrawers(); - setBagDrawer(true); - setIgnoreFeatures(true); - setObjectKey(b.key()); - moveMap( - b.centerLocation().latitude, - b.centerLocation().longitude, - zoomLevels.far, - isMobile - ); - } - }; - bagMarkerData.set(b.key(), mData); - bagEntries.push({ - center: [b.centerLocation().longitude, b.centerLocation().latitude], - id: b.key(), - place_name: b.name(), - place_type: ["grainBag"], - address: "", - bbox: [0,0,0,0], - context: [], - geometry: {type: "Point", coordinates: [b.centerLocation().longitude, b.centerLocation().latitude]}, - properties: {}, - relevance: 0, - text: "", - type: "Feature" - }); + if(resp.data.grainBags){ + + resp.data.grainBags.forEach(bag => { + let b = BagModel.create(bag); + bags.set(b.key(), b); + if (bag.settings) { + if (!b.settings.startLocation?.longitude && !b.settings.endLocation?.longitude) { + bagOp.push(b); + } else { + //build the data for the marker + //TODO-CS: think about making the creation of marker data a function in the object model + let mData: MarkerData = { + title: b.name(), + longitude: b.centerLocation().longitude, + latitude: b.centerLocation().latitude, + visibleLevels: { max: 13 }, + colour: b.settings.theme?.color ?? "white", + clickFunc: (e, i, isMobile) => { + clickDelay(); + closeDrawers(); + setBagDrawer(true); + setIgnoreFeatures(true); + setObjectKey(b.key()); + moveMap( + b.centerLocation().latitude, + b.centerLocation().longitude, + zoomLevels.far, + isMobile + ); + } + }; + bagMarkerData.set(b.key(), mData); + bagEntries.push({ + center: [b.centerLocation().longitude, b.centerLocation().latitude], + id: b.key(), + place_name: b.name(), + place_type: ["grainBag"], + address: "", + bbox: [0,0,0,0], + context: [], + geometry: {type: "Point", coordinates: [b.centerLocation().longitude, b.centerLocation().latitude]}, + properties: {}, + relevance: 0, + text: "", + type: "Feature" + }); + } } - } - }); + }); + } setBagOptions(bagOp); setGrainBags(bags); grainBagsRef.current = bags; @@ -382,19 +387,21 @@ import { Result } from "@mapbox/mapbox-gl-geocoder"; binYardAPI .listBinYards(400, 0, "asc", undefined, undefined, undefined, as) .then(resp => { - resp.data.yard.forEach(yard => { - if (yard.settings) { - yardMap.set(yard.settings.key, yard.settings); - if ( - (!yard.settings.latitude && !yard.settings.longitude) || - (yard.settings.latitude === 0 && yard.settings.longitude === 0) - ) { - yardOps.push(yard.settings); - } else { - let mData: MarkerData = { - title: yard.settings.name, - longitude: yard.settings.longitude, - latitude: yard.settings.latitude, + if(resp.data.yard){ + + resp.data.yard.forEach(yard => { + if (yard.settings) { + yardMap.set(yard.settings.key, yard.settings); + if ( + (!yard.settings.latitude && !yard.settings.longitude) || + (yard.settings.latitude === 0 && yard.settings.longitude === 0) + ) { + yardOps.push(yard.settings); + } else { + let mData: MarkerData = { + title: yard.settings.name, + longitude: yard.settings.longitude, + latitude: yard.settings.latitude, colour: yard.settings.theme?.color ?? "green", markerIcon: , visibleLevels: { max: 17 }, @@ -429,6 +436,7 @@ import { Result } from "@mapbox/mapbox-gl-geocoder"; } } }); + } setYardMarkerData(newYardMarkers); setYardSearchEntries(yardEntries); setBinYards(yardMap); @@ -447,6 +455,9 @@ import { Result } from "@mapbox/mapbox-gl-geocoder"; let markerData: Map = new Map(); let searchEntries: Result[] = []; let binOp: IBin[] = []; + if(resp.data.bins){ + + resp.data.bins.forEach(bin => { let b = IBin.create(bin); binMap.set(b.key(), b); @@ -495,6 +506,7 @@ import { Result } from "@mapbox/mapbox-gl-geocoder"; } } }); + } setBinMarkerData(markerData); setBinSearchEntries(searchEntries); setBins(binMap); @@ -514,6 +526,9 @@ import { Result } from "@mapbox/mapbox-gl-geocoder"; let searchEntries: Result[] = []; let options: DeviceModel[] = []; + if(resp.data.devices){ + + resp.data.devices.forEach((device, i) => { //add device to the main map let d = DeviceModel.any(device); @@ -553,6 +568,7 @@ import { Result } from "@mapbox/mapbox-gl-geocoder"; } } }); + } setDevices(map); setDeviceOptions(options); setDeviceMarkerData(newDevMarkers); @@ -725,6 +741,9 @@ import { Result } from "@mapbox/mapbox-gl-geocoder"; let fmMap: Map = new Map(); let markerData: Map = new Map(); let searchEntries: Result[] = []; + if(resp.data.fieldMarker){ + + resp.data.fieldMarker.forEach(fieldMarker => { let fm = FieldMarker.create(fieldMarker); fmMap.set(fm.key(), fm); @@ -760,6 +779,7 @@ import { Result } from "@mapbox/mapbox-gl-geocoder"; place_type: ["fieldMarker"] } as Result); }); + } setFieldMarkers(fmMap); setFieldMarkerData(markerData); setFieldMarkerSearchEntries(searchEntries); diff --git a/src/providers/pond/gateAPI.tsx b/src/providers/pond/gateAPI.tsx index 6f540dc..b9ab561 100644 --- a/src/providers/pond/gateAPI.tsx +++ b/src/providers/pond/gateAPI.tsx @@ -81,6 +81,7 @@ export interface IGateInterface { otherTeam?: string ) => Promise>; //new call for getting report data for gates + gateReportData: (gates: string[], start: string, end: string, otherTeam?: string) => Promise> } export const GateAPIcontext = createContext({} as IGateInterface); @@ -348,6 +349,24 @@ export default function GateProvider(props: PropsWithChildren) { ); }; + const gateReportData = ( + gates: string[], + start: string, + end: string, + otherTeam?: string + ) => { + const view = otherTeam ? otherTeam : as + let url = pondURL("reports/gates?keys=" + gates.toString() + "start=" + start + "&end=" + end + "&as=" + view) + return new Promise>((resolve, reject) => { + get(url).then(resp => { + resp.data = pond.GateReportDataResponse.fromObject(resp.data) + return resolve(resp) + }).catch(err => { + return reject(err) + }) + }) + } + return ( ) { updatePrefs, listGateAirflow, listGateMeasurements, - listGateFlowEvents + listGateFlowEvents, + gateReportData }}> {children} diff --git a/src/reports/MiPCA/GateReports.tsx b/src/reports/MiPCA/GateReports.tsx index 8fa7f51..73bd5c9 100644 --- a/src/reports/MiPCA/GateReports.tsx +++ b/src/reports/MiPCA/GateReports.tsx @@ -1,8 +1,27 @@ -import React from "react" +import { DialogActions, DialogContent, DialogTitle } from "@mui/material" +import ResponsiveDialog from "common/ResponsiveDialog" +import { useGateAPI } from "providers" +import React, { useEffect } from "react" -export default function GateReports(){ +interface Props { + open: boolean + onClose: () => void + gate?: string //if the gate key is passed in just generate for that gate, otherwise give the user a way of selecting which gates +} + +export default function GateReports(props: Props){ + const {gate, open, onClose} = props + const gateAPI = useGateAPI() //load all of the gates for the user/team + useEffect(()=>{ + if(gate) return //if there was a gate passed in we dont need to load them + gateAPI.listGates(0, 0).then(resp => { + console.log(resp.data) + }).catch(err => { + + }) + },[gate]) //selection table to select which gates to generate a report @@ -13,6 +32,12 @@ export default function GateReports(){ */ return ( - + + Gate Reports + + + + + ) } \ No newline at end of file