Skip to content

Commit 90700e0

Browse files
feat: Load map bounds on data load (#242)
* feat: Save bounds on data load * feat: Load map bounds on data load f9b1d89
1 parent 3d84bfe commit 90700e0

File tree

3 files changed

+102
-35
lines changed

3 files changed

+102
-35
lines changed

src/App.js

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ class App extends React.Component {
6969
uploadedDatasets: [null, null, null, null, null],
7070
activeDatasetIndex: null,
7171
activeMenuIndex: null,
72+
initialMapBounds: null,
7273
selectedRowIndexPerDataset: [-1, -1, -1, -1, -1],
74+
currentLogData: this.props.logData,
7375
};
7476
// Realtime updates are too heavy. There must be a better/ react way
7577
this.onSliderChangeDebounced = _.debounce((timeRange) => this.onSliderChange(timeRange), 25);
@@ -178,7 +180,7 @@ class App extends React.Component {
178180
},
179181
],
180182
(toggle) => {
181-
return toggle.solutionTypes.indexOf(this.props.logData.solutionType) !== -1;
183+
return toggle.solutionTypes.indexOf(this.state.currentLogData.solutionType) !== -1;
182184
}
183185
);
184186
this.setFeaturedObject = this.setFeaturedObject.bind(this);
@@ -316,7 +318,7 @@ class App extends React.Component {
316318
this.setState((prevState) => {
317319
const minDate = new Date(prevState.timeRange.minTime);
318320
const maxDate = new Date(prevState.timeRange.maxTime);
319-
const logs = this.props.logData.tripLogs.getLogs_(minDate, maxDate).value();
321+
const logs = this.state.currentLogData.tripLogs.getLogs_(minDate, maxDate).value();
320322
if (logs.length > 0) {
321323
const firstRow = logs[0];
322324
setTimeout(() => this.focusOnSelectedRow(), 0);
@@ -334,7 +336,7 @@ class App extends React.Component {
334336
selectLastRow = () => {
335337
const minDate = new Date(this.state.timeRange.minTime);
336338
const maxDate = new Date(this.state.timeRange.maxTime);
337-
const logsWrapper = this.props.logData.tripLogs.getLogs_(minDate, maxDate);
339+
const logsWrapper = this.state.currentLogData.tripLogs.getLogs_(minDate, maxDate);
338340
const logs = logsWrapper.value();
339341
if (logs.length > 0) {
340342
const lastRow = logs[logs.length - 1];
@@ -349,7 +351,7 @@ class App extends React.Component {
349351
const { featuredObject } = this.state;
350352
const minDate = new Date(this.state.timeRange.minTime);
351353
const maxDate = new Date(this.state.timeRange.maxTime);
352-
const logs = this.props.logData.tripLogs.getLogs_(minDate, maxDate).value();
354+
const logs = this.state.currentLogData.tripLogs.getLogs_(minDate, maxDate).value();
353355
let newFeaturedObject = featuredObject;
354356
const currentIndex = logs.findIndex((log) => log.timestamp === featuredObject.timestamp);
355357
if (direction === "next" && currentIndex < logs.length - 1) {
@@ -433,13 +435,18 @@ class App extends React.Component {
433435
log(`Uploading file ${file.name} for button ${index}`);
434436
await uploadFile(file, index);
435437
log(`File ${file.name} uploaded successfully for button ${index}`);
436-
this.setState((prevState) => {
437-
const newUploadedDatasets = [...prevState.uploadedDatasets];
438-
newUploadedDatasets[index] = "Uploaded";
439-
log(`Updated state for button ${index}:`, newUploadedDatasets);
440-
return { uploadedDatasets: newUploadedDatasets, activeDatasetIndex: index };
441-
});
442-
this.switchDataset(index);
438+
this.setState(
439+
(prevState) => {
440+
const newUploadedDatasets = [...prevState.uploadedDatasets];
441+
newUploadedDatasets[index] = "Uploaded";
442+
log(`Updated dataset button state for index ${index}:`, newUploadedDatasets);
443+
return { uploadedDatasets: newUploadedDatasets };
444+
},
445+
() => {
446+
console.log(`handleFileUpload: setState callback executed for index ${index}, now switching dataset.`);
447+
this.switchDataset(index);
448+
}
449+
);
443450
} catch (error) {
444451
console.error("Error uploading file:", error);
445452
}
@@ -591,15 +598,23 @@ class App extends React.Component {
591598

592599
// Update the current dataset if this is the active one
593600
if (this.state.activeDatasetIndex === index) {
601+
log(`handlePruneClick: Pruning active dataset ${index}, updating state.`);
594602
const tripLogs = new TripLogs(data.rawLogs, data.solutionType);
595-
this.props.logData.tripLogs = tripLogs;
596-
this.props.logData.solutionType = data.solutionType;
597603

598-
// Force update of components
599-
this.forceUpdate();
600-
601-
// Select first row after pruning
602-
this.selectFirstRow();
604+
this.setState(
605+
(prevState) => ({
606+
currentLogData: {
607+
...prevState.currentLogData,
608+
tripLogs: tripLogs,
609+
solutionType: data.solutionType,
610+
},
611+
}),
612+
() => {
613+
log("handlePruneClick: setState callback executed, selecting first row.");
614+
// Select first row after pruning
615+
this.selectFirstRow();
616+
}
617+
);
603618
}
604619

605620
toast.success(`Dataset pruned: removed ${removeCount} logs outside the selected time range.`);
@@ -787,17 +802,19 @@ class App extends React.Component {
787802
if (data && data.rawLogs && Array.isArray(data.rawLogs) && data.rawLogs.length > 0) {
788803
const tripLogs = new TripLogs(data.rawLogs, data.solutionType);
789804
this.setState(
790-
{
791-
activeDatasetIndex: index,
792-
timeRange: { minTime: tripLogs.minDate.getTime(), maxTime: tripLogs.maxDate.getTime() },
805+
(prevState) => {
806+
return {
807+
activeDatasetIndex: index,
808+
timeRange: { minTime: tripLogs.minDate.getTime(), maxTime: tripLogs.maxDate.getTime() },
809+
initialMapBounds: data.bounds,
810+
currentLogData: {
811+
...prevState.currentLogData,
812+
tripLogs: tripLogs,
813+
solutionType: data.solutionType,
814+
},
815+
};
793816
},
794817
() => {
795-
// Update the logData prop with the new TripLogs instance
796-
this.props.logData.tripLogs = tripLogs;
797-
this.props.logData.solutionType = data.solutionType;
798-
799-
// Force an update of child components
800-
this.forceUpdate();
801818
log(`Switched to dataset ${index}`);
802819
log(`New time range: ${tripLogs.minDate} - ${tripLogs.maxDate}`);
803820

@@ -844,11 +861,11 @@ class App extends React.Component {
844861
this.selectFirstRow();
845862
}
846863
}, 300); // Increased delay to ensure map is fully initialized
864+
865+
// Update map and associated data
866+
this.updateMapAndAssociatedData();
847867
}
848868
);
849-
850-
// Update map and associated data
851-
this.updateMapAndAssociatedData();
852869
} else {
853870
console.error(`Invalid or empty data structure for dataset ${index}`);
854871
}
@@ -876,7 +893,7 @@ class App extends React.Component {
876893
<div className="map-container">
877894
<Map
878895
key={`map-${this.state.activeDatasetIndex}`}
879-
logData={this.props.logData}
896+
logData={this.state.currentLogData}
880897
rangeStart={this.state.timeRange.minTime}
881898
rangeEnd={this.state.timeRange.maxTime}
882899
selectedRow={this.state.featuredObject}
@@ -886,10 +903,11 @@ class App extends React.Component {
886903
setTimeRange={this.setTimeRange}
887904
setCenterOnLocation={this.setCenterOnLocation}
888905
focusSelectedRow={this.focusOnSelectedRow}
906+
initialMapBounds={this.state.initialMapBounds}
889907
/>
890908
</div>
891909
<TimeSlider
892-
logData={this.props.logData}
910+
logData={this.state.currentLogData}
893911
curMin={this.state.timeRange.minTime}
894912
curMax={this.state.timeRange.maxTime}
895913
onSliderChange={this.onSliderChangeDebounced}
@@ -941,7 +959,7 @@ class App extends React.Component {
941959
</div>
942960
<div style={{ flex: 1, overflow: "auto" }}>
943961
<LogTable
944-
logData={this.props.logData}
962+
logData={this.state.currentLogData}
945963
style={{ width: "100%" }}
946964
timeRange={this.state.timeRange}
947965
extraColumns={this.state.extraColumns}

src/Map.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,24 @@ function MyMapComponent(props) {
116116
const urlCenter = getQueryStringValue("center");
117117
const urlHeading = getQueryStringValue("heading");
118118
map = initializeMapObject(ref.current);
119-
const vehicleBounds = addTripPolys(map);
119+
addTripPolys(map);
120+
120121
if (urlZoom && urlCenter) {
121122
log("setting zoom & center from url", urlZoom, urlCenter);
122123
map.setZoom(parseInt(urlZoom));
123124
map.setCenter(JSON.parse(urlCenter));
125+
} else if (props.initialMapBounds) {
126+
log("Fitting map to pre-calculated dataset bounds.");
127+
const { north, south, east, west } = props.initialMapBounds;
128+
const bounds = new window.google.maps.LatLngBounds(
129+
new window.google.maps.LatLng(south, west),
130+
new window.google.maps.LatLng(north, east)
131+
);
132+
map.fitBounds(bounds);
124133
} else {
125-
map.fitBounds(vehicleBounds);
134+
log("No bounds provided, defaulting to a world view.");
135+
map.setCenter({ lat: 20, lng: 0 });
136+
map.setZoom(2);
126137
}
127138

128139
if (urlHeading) {
@@ -521,11 +532,13 @@ function Map(props) {
521532
return (
522533
<APIProvider apiKey={apikey} solutionChannel="GMP_visgl_reactgooglemaps_v1_GMP_FLEET_DEBUGGER">
523534
<MapContent
535+
logData={props.logData}
524536
rangeStart={props.rangeStart}
525537
rangeEnd={props.rangeEnd}
526538
selectedRow={props.selectedRow}
527539
toggles={props.toggles}
528540
toggleOptions={props.toggleOptions}
541+
initialMapBounds={props.initialMapBounds}
529542
/>
530543
</APIProvider>
531544
);

src/localStorage.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// src/localStorage.js
22
import JSZip from "jszip";
33
import { DEFAULT_API_KEY } from "./constants";
4+
import _ from "lodash";
45
import { log } from "./Utils";
56

67
const DB_NAME = "FleetDebuggerDB";
@@ -275,13 +276,48 @@ export function ensureCorrectFormat(data) {
275276
const solutionType = isLMFS ? "LMFS" : "ODRD";
276277
console.log(`Determined solution type: ${solutionType}`);
277278

279+
const bounds = {
280+
north: -90,
281+
south: 90,
282+
east: -180,
283+
west: 180,
284+
};
285+
let hasPoints = false;
286+
287+
mergedLogs.forEach((row) => {
288+
const lat =
289+
_.get(row, "jsonPayload.response.lastLocation.rawLocation.latitude") ||
290+
_.get(row, "jsonPayload.response.lastlocation.rawlocation.latitude");
291+
const lng =
292+
_.get(row, "jsonPayload.response.lastLocation.rawLocation.longitude") ||
293+
_.get(row, "jsonPayload.response.lastlocation.rawlocation.longitude");
294+
295+
if (lat != null && lng != null) {
296+
if (!hasPoints) {
297+
bounds.north = lat;
298+
bounds.south = lat;
299+
bounds.east = lng;
300+
bounds.west = lng;
301+
hasPoints = true;
302+
} else {
303+
bounds.north = Math.max(bounds.north, lat);
304+
bounds.south = Math.min(bounds.south, lat);
305+
bounds.east = Math.max(bounds.east, lng);
306+
bounds.west = Math.min(bounds.west, lng);
307+
}
308+
}
309+
});
310+
311+
if (!hasPoints) log("Bounds Calculation Failed: Could not find vehicle location data in any row.");
312+
278313
return {
279314
APIKEY: DEFAULT_API_KEY,
280315
vehicle: "",
281316
projectId: "",
282317
logSource: "Direct Cloud Logging",
283318
solutionType: solutionType,
284319
rawLogs: mergedLogs,
320+
bounds: hasPoints ? bounds : null,
285321
};
286322
}
287323

0 commit comments

Comments
 (0)