Skip to content

Commit 2da0e57

Browse files
feat: Refactor of Map.js and Toggles (#243) bc2c9ae
1 parent bbc6d70 commit 2da0e57

File tree

5 files changed

+948
-1353
lines changed

5 files changed

+948
-1353
lines changed

src/App.js

Lines changed: 37 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,7 @@ import "./global.css";
2222
import { log } from "./Utils";
2323
import { toast, ToastContainer } from "react-toastify";
2424
import "react-toastify/dist/ReactToastify.css";
25-
26-
/**
27-
* returns the default value for the button from the url
28-
*/
29-
function getToggleDefault(urlKey, defaultVal) {
30-
const urlVal = getQueryStringValue(urlKey);
31-
if (urlVal === "true") {
32-
defaultVal = true;
33-
}
34-
return defaultVal;
35-
}
25+
import { ALL_TOGGLES, getVisibleToggles } from "./MapToggles";
3626

3727
class App extends React.Component {
3828
constructor(props) {
@@ -41,7 +31,7 @@ class App extends React.Component {
4131
const nowDate = new Date();
4232
let urlMinTime = getQueryStringValue("minTime");
4333
let urlMaxTime = getQueryStringValue("maxTime");
44-
this.initialMinTime = urlMinTime ? parseInt(urlMinTime) : 0; // default max time to 1 year in the future
34+
this.initialMinTime = urlMinTime ? parseInt(urlMinTime) : 0;
4535
this.initialMaxTime = urlMaxTime ? parseInt(urlMaxTime) : nowDate.setFullYear(nowDate.getFullYear() + 1);
4636
this.focusOnRowFunction = null;
4737
this.state = {
@@ -50,162 +40,25 @@ class App extends React.Component {
5040
playSpeed: 1000,
5141
featuredObject: { msg: "Click a table row to select object" },
5242
extraColumns: [],
53-
toggleOptions: {
54-
showGPSBubbles: getToggleDefault("showGPSBubbles", false),
55-
showHeading: getToggleDefault("showHeading", false),
56-
showSpeed: getToggleDefault("showSpeed", false),
57-
showTraffic: getToggleDefault("showTraffic", false),
58-
showTripStatus: getToggleDefault("showTripStatus", false),
59-
showDwellLocations: getToggleDefault("showDwellLocations", false),
60-
showNavStatus: getToggleDefault("showNavStatus", false),
61-
showETADeltas: getToggleDefault("showETADeltas", false),
62-
showHighVelocityJumps: getToggleDefault("showHighVelocityJumps", false),
63-
showMissingUpdates: getToggleDefault("showMissingUpdates", false),
64-
showTasksAsCreated: getToggleDefault("showTasksAsCreated", false),
65-
showPlannedPaths: getToggleDefault("showPlannedPaths", false),
66-
showLiveJS: getToggleDefault("showLiveJS", false),
67-
showClientServerTimeDeltas: getToggleDefault("showClientServerTimeDeltas", false),
68-
},
43+
toggleOptions: Object.fromEntries(ALL_TOGGLES.map((t) => [t.id, false])),
6944
uploadedDatasets: [null, null, null, null, null],
7045
activeDatasetIndex: null,
7146
activeMenuIndex: null,
7247
initialMapBounds: null,
7348
selectedRowIndexPerDataset: [-1, -1, -1, -1, -1],
7449
currentLogData: this.props.logData,
7550
};
76-
// Realtime updates are too heavy. There must be a better/ react way
7751
this.onSliderChangeDebounced = _.debounce((timeRange) => this.onSliderChange(timeRange), 25);
78-
79-
// TODO: refactor so that visualizations are registered
80-
// rather than enumerated here?
81-
this.toggles = _.filter(
82-
[
83-
{
84-
id: "showGPSBubbles",
85-
name: "GPS Accuracy",
86-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/GPSAccuracy.md",
87-
columns: ["lastlocation.rawlocationaccuracy", "lastlocation.locationsensor"],
88-
solutionTypes: ["ODRD", "LMFS"],
89-
},
90-
{
91-
id: "showHeading",
92-
name: "Heading",
93-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/Heading.md",
94-
columns: ["lastlocation.heading", "lastlocation.headingaccuracy"],
95-
solutionTypes: ["ODRD", "LMFS"],
96-
},
97-
{
98-
id: "showSpeed",
99-
name: "Speed",
100-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/Speed.md",
101-
columns: [],
102-
solutionTypes: ["ODRD", "LMFS"],
103-
},
104-
{
105-
id: "showTripStatus",
106-
name: "Trip Status",
107-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/TripStatus.md",
108-
columns: [],
109-
solutionTypes: ["ODRD"],
110-
},
111-
{
112-
id: "showNavStatus",
113-
name: "Navigation Status",
114-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/NavStatus.md",
115-
columns: [],
116-
solutionTypes: ["ODRD", "LMFS"],
117-
},
118-
{
119-
id: "showTasksAsCreated",
120-
name: "Tasks",
121-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/Tasks.md",
122-
columns: [],
123-
solutionTypes: ["LMFS"],
124-
},
125-
{
126-
id: "showPlannedPaths",
127-
name: "Planned Paths",
128-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/PlannedPaths.md",
129-
columns: [],
130-
solutionTypes: ["LMFS"],
131-
},
132-
{
133-
id: "showDwellLocations",
134-
name: "Dwell Locations",
135-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/DwellTimes.md",
136-
columns: [],
137-
solutionTypes: ["ODRD", "LMFS"],
138-
},
139-
{
140-
id: "showHighVelocityJumps",
141-
name: "Jumps (unrealistic velocity)",
142-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/VelocityJumps.md",
143-
columns: [],
144-
solutionTypes: ["ODRD", "LMFS"],
145-
},
146-
{
147-
id: "showMissingUpdates",
148-
name: "Jumps (Temporal)",
149-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/MissingUpdates.md",
150-
columns: ["temporal_gap"],
151-
solutionTypes: ["ODRD", "LMFS"],
152-
},
153-
{
154-
id: "showClientServerTimeDeltas",
155-
name: "Client/Server Time Deltas",
156-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/README.md",
157-
columns: [],
158-
solutionTypes: ["ODRD", "LMFS"],
159-
},
160-
{
161-
id: "showETADeltas",
162-
name: "ETA Deltas",
163-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/EtaDeltas.md",
164-
columns: ["request.vehicle.etatofirstwaypoint"],
165-
solutionTypes: ["ODRD"],
166-
},
167-
{
168-
id: "showTraffic",
169-
name: "Live Traffic",
170-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/README.md",
171-
columns: [],
172-
solutionTypes: ["ODRD", "LMFS"],
173-
},
174-
{
175-
id: "showLiveJS",
176-
name: "Live Journey Sharing",
177-
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/README.md",
178-
columns: [],
179-
solutionTypes: ["ODRD", "LMFS"],
180-
},
181-
],
182-
(toggle) => {
183-
return toggle.solutionTypes.indexOf(this.state.currentLogData.solutionType) !== -1;
184-
}
185-
);
18652
this.setFeaturedObject = this.setFeaturedObject.bind(this);
18753
this.setTimeRange = this.setTimeRange.bind(this);
18854
}
18955

190-
/*
191-
* Update react state from data in the url. This could/should be
192-
* cleaned up. The pure react state is actually set properly in the
193-
* constructor ... all this does is update the map and associated
194-
* data (once it's loaded). Given this split it's definitely possible
195-
* that this just overwrites settings a quickfingered user already
196-
* changed.
197-
*/
19856
updateMapAndAssociatedData = () => {
19957
this.setTimeRange(this.state.timeRange.minTime, this.state.timeRange.maxTime);
200-
_.map(this.toggles, (toggle) => {
201-
const urlVal = getQueryStringValue(toggle.id);
202-
if (urlVal === "true") {
203-
this.updateToggleState(true, toggle.id, toggle.columns);
204-
}
205-
});
20658
};
20759

20860
componentDidMount() {
61+
log(`Initial device pixel ratio: ${window.devicePixelRatio}`);
20962
this.initializeData().then(() => {
21063
this.updateMapAndAssociatedData();
21164
});
@@ -221,34 +74,27 @@ class App extends React.Component {
22174

22275
updateToggleState(newValue, toggleName, jsonPaths) {
22376
this.setState((prevState) => {
224-
prevState.toggleOptions[toggleName] = newValue;
225-
setQueryStringValue(toggleName, newValue);
226-
const extraColumns = _.clone(prevState.extraColumns);
227-
_.forEach(jsonPaths, (path) => {
228-
if (newValue) {
229-
extraColumns.push(path);
230-
} else {
231-
_.pull(extraColumns, path);
232-
}
233-
});
234-
prevState.extraColumns = _.uniq(extraColumns);
235-
return prevState;
77+
const newToggleOptions = {
78+
...prevState.toggleOptions,
79+
[toggleName]: newValue,
80+
};
81+
82+
const newExtraColumns = newValue
83+
? _.union(prevState.extraColumns, jsonPaths)
84+
: _.difference(prevState.extraColumns, jsonPaths);
85+
86+
return {
87+
toggleOptions: newToggleOptions,
88+
extraColumns: newExtraColumns,
89+
};
23690
});
23791
}
23892

239-
/*
240-
* Updates react state associated with the slider and calls into
241-
* the non-react map code to do the same.
242-
*/
24393
onSliderChange(timeRange) {
24494
this.setTimeRange(timeRange.minTime, timeRange.maxTime);
24595
}
24696

247-
/*
248-
* Callback to updated selected log row
249-
*/
25097
onSelectionChange(selectedRow, rowIndex) {
251-
// Save both the selected row and its index for the current dataset
25298
if (this.state.activeDatasetIndex !== null && rowIndex !== undefined) {
25399
this.setState((prevState) => {
254100
const newSelectedIndexes = [...prevState.selectedRowIndexPerDataset];
@@ -264,9 +110,6 @@ class App extends React.Component {
264110
}
265111
}
266112

267-
/*
268-
* Set the featured object
269-
*/
270113
setFeaturedObject(featuredObject) {
271114
this.setState({ featuredObject: featuredObject });
272115
}
@@ -281,9 +124,6 @@ class App extends React.Component {
281124
}
282125
};
283126

284-
/*
285-
* exposes editing of the timeRange state
286-
*/
287127
setTimeRange(minTime, maxTime, callback) {
288128
setQueryStringValue("minTime", minTime);
289129
setQueryStringValue("maxTime", maxTime);
@@ -818,29 +658,22 @@ class App extends React.Component {
818658
log(`Switched to dataset ${index}`);
819659
log(`New time range: ${tripLogs.minDate} - ${tripLogs.maxDate}`);
820660

821-
// After dataset is loaded, try to restore the previously selected row index
822661
const savedRowIndex = this.state.selectedRowIndexPerDataset[index];
823662
log(`Attempting to restore row at index ${savedRowIndex} for dataset ${index}`);
824663

825-
// Wait for map and components to fully initialize
826664
setTimeout(() => {
827665
if (savedRowIndex >= 0) {
828-
// Get current log data with the new time range
829666
const minDate = new Date(this.state.timeRange.minTime);
830667
const maxDate = new Date(this.state.timeRange.maxTime);
831668
const logs = tripLogs.getLogs_(minDate, maxDate).value();
832669

833-
// Check if the saved index is valid for the current dataset
834670
if (savedRowIndex < logs.length) {
835671
log(`Restoring row at index ${savedRowIndex}`);
836672
const rowToSelect = logs[savedRowIndex];
837673

838-
// First update the featured object
839674
this.setState({ featuredObject: rowToSelect }, () => {
840-
// Then focus on the row in the table
841675
this.focusOnSelectedRow();
842676

843-
// And finally center the map on the location (simulating a long press)
844677
const lat = _.get(rowToSelect, "lastlocation.rawlocation.latitude");
845678
const lng = _.get(rowToSelect, "lastlocation.rawlocation.longitude");
846679

@@ -856,13 +689,11 @@ class App extends React.Component {
856689
this.selectFirstRow();
857690
}
858691
} else {
859-
// If no saved selection or invalid index, select first row
860692
log(`No previously saved row index for dataset ${index}, selecting first row`);
861693
this.selectFirstRow();
862694
}
863-
}, 300); // Increased delay to ensure map is fully initialized
695+
}, 300);
864696

865-
// Update map and associated data
866697
this.updateMapAndAssociatedData();
867698
}
868699
);
@@ -875,15 +706,15 @@ class App extends React.Component {
875706
};
876707

877708
toggleClickHandler(id) {
878-
const toggle = _.find(this.toggles, { id });
709+
const toggle = _.find(ALL_TOGGLES, { id });
879710
const newValue = !this.state.toggleOptions[id];
880711
this.updateToggleState(newValue, id, toggle.columns);
881712
}
882713

883714
render() {
884-
const selectedEventTime = this.state.featuredObject?.timestamp
885-
? new Date(this.state.featuredObject.timestamp).getTime()
886-
: null;
715+
const { featuredObject, timeRange, currentLogData, toggleOptions, extraColumns } = this.state;
716+
const selectedEventTime = featuredObject?.timestamp ? new Date(featuredObject.timestamp).getTime() : null;
717+
const visibleToggles = getVisibleToggles(currentLogData.solutionType);
887718

888719
return (
889720
<div className="app-container">
@@ -893,12 +724,12 @@ class App extends React.Component {
893724
<div className="map-container">
894725
<Map
895726
key={`map-${this.state.activeDatasetIndex}`}
896-
logData={this.state.currentLogData}
897-
rangeStart={this.state.timeRange.minTime}
898-
rangeEnd={this.state.timeRange.maxTime}
899-
selectedRow={this.state.featuredObject}
900-
toggles={this.toggles}
901-
toggleOptions={this.state.toggleOptions}
727+
logData={currentLogData}
728+
rangeStart={timeRange.minTime}
729+
rangeEnd={timeRange.maxTime}
730+
selectedRow={featuredObject}
731+
toggles={visibleToggles}
732+
toggleOptions={toggleOptions}
902733
setFeaturedObject={this.setFeaturedObject}
903734
setTimeRange={this.setTimeRange}
904735
setCenterOnLocation={this.setCenterOnLocation}
@@ -907,18 +738,18 @@ class App extends React.Component {
907738
/>
908739
</div>
909740
<TimeSlider
910-
logData={this.state.currentLogData}
911-
curMin={this.state.timeRange.minTime}
912-
curMax={this.state.timeRange.maxTime}
741+
logData={currentLogData}
742+
curMin={timeRange.minTime}
743+
curMax={timeRange.maxTime}
913744
onSliderChange={this.onSliderChangeDebounced}
914745
selectedEventTime={selectedEventTime}
915746
onRowSelect={(row, rowIndex) => this.onSelectionChange(row, rowIndex)}
916747
centerOnLocation={this.centerOnLocation}
917748
focusSelectedRow={this.focusOnSelectedRow}
918749
/>
919750
<ToggleBar
920-
toggles={this.toggles}
921-
toggleState={this.state.toggleOptions}
751+
toggles={visibleToggles}
752+
toggleState={toggleOptions}
922753
clickHandler={(id) => this.toggleClickHandler(id)}
923754
/>
924755
<div className="nav-controls">
@@ -959,21 +790,18 @@ class App extends React.Component {
959790
</div>
960791
<div style={{ flex: 1, overflow: "auto" }}>
961792
<LogTable
962-
logData={this.state.currentLogData}
793+
logData={currentLogData}
963794
style={{ width: "100%" }}
964-
timeRange={this.state.timeRange}
965-
extraColumns={this.state.extraColumns}
795+
timeRange={timeRange}
796+
extraColumns={extraColumns}
966797
onSelectionChange={(rowData, rowIndex) => this.onSelectionChange(rowData, rowIndex)}
967798
setFocusOnRowFunction={this.setFocusOnRowFunction}
968799
centerOnLocation={this.centerOnLocation}
969800
/>
970801
</div>
971802
</div>
972803
<div className="dataframe-section">
973-
<Dataframe
974-
featuredObject={this.state.featuredObject}
975-
onClick={(select) => this.onDataframePropClick(select)}
976-
/>
804+
<Dataframe featuredObject={featuredObject} onClick={(select) => this.onDataframePropClick(select)} />
977805
</div>
978806
</div>
979807
);

0 commit comments

Comments
 (0)