Skip to content

Commit 6e09e5a

Browse files
feat: support for extra log source (#228)
* fix: Better DayTime format 02-05 17:02:33 vs 05T17:02:33.321 * feat: Support for snake_case JSON * fix: remove some redundant columns * fix: traffic styles may have different format 334d494
1 parent e3736d2 commit 6e09e5a

File tree

7 files changed

+133
-9
lines changed

7 files changed

+133
-9
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dune-buggy",
3-
"version": "1.12.0",
3+
"version": "1.12.1",
44
"description": "",
55
"main": "index.js",
66
"repository": {

src/App.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class App extends React.Component {
8989
id: "showSpeed",
9090
name: "Speed",
9191
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/Speed.md",
92-
columns: ["lastlocation.speed"],
92+
columns: [],
9393
solutionTypes: ["ODRD", "LMFS"],
9494
},
9595
{
@@ -131,7 +131,7 @@ class App extends React.Component {
131131
id: "showHighVelocityJumps",
132132
name: "Jumps (unrealistic velocity)",
133133
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/docs/VelocityJumps.md",
134-
columns: ["lastlocation.speed"],
134+
columns: [],
135135
solutionTypes: ["ODRD", "LMFS"],
136136
},
137137
{
@@ -145,7 +145,7 @@ class App extends React.Component {
145145
id: "showClientServerTimeDeltas",
146146
name: "Client/Server Time Deltas",
147147
docLink: "https://github.com/googlemaps/fleet-debugger/blob/main/README.md",
148-
columns: ["response.laslLocation.rawlocationlime", "response.laslLocation.serverlime"],
148+
columns: [],
149149
solutionTypes: ["ODRD", "LMFS"],
150150
},
151151
{

src/LogTable.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ function LogTable(props) {
162162
{
163163
Header: "DayTime",
164164
accessor: "formattedDate",
165-
Cell: ({ cell: { value } }) => value.substring(8, 10) + "T" + value.substring(11, 23),
165+
Cell: ({ cell: { value } }) => value.substring(5, 10) + " " + value.substring(11, 19),
166166
width: columnRegularWidth,
167167
className: "logtable-cell",
168168
solutionTypes: ["ODRD", "LMFS"],

src/TrafficPolyline.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ import { log } from "./Utils";
55

66
export const TRAFFIC_COLORS = {
77
STYLE_NO_DATA: "#808080", // Gray
8+
NO_DATA: "#808080",
89
STYLE_NORMAL: "#4285F4", // Google Maps Blue
10+
NORMAL: "#4285F4",
911
STYLE_SLOWER_TRAFFIC: "#FFA500", // Orange
12+
SLOWER_TRAFFIC: "#FFA500",
1013
STYLE_TRAFFIC_JAM: "#FF0000", // Red
14+
TRAFFIC_JAM: "#FF0000",
1115
};
1216

1317
export class TrafficPolyline {

src/localStorage.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,45 @@ export function parseJsonContent(content) {
140140
}, {});
141141
};
142142

143+
const processJsonObject = (obj) => {
144+
if (obj === null || typeof obj !== "object") return obj;
145+
if (Array.isArray(obj)) return obj.map(processJsonObject);
146+
147+
return Object.keys(obj).reduce((result, key) => {
148+
const newKey = key.replace(/_/g, "");
149+
let value = obj[key];
150+
151+
// Check if this is a value object with only a 'value' property and flatten
152+
if (
153+
value !== null &&
154+
typeof value === "object" &&
155+
!Array.isArray(value) &&
156+
Object.keys(value).length === 1 &&
157+
"value" in value
158+
) {
159+
value = value.value;
160+
} else if (typeof value === "object" && value !== null) {
161+
// Recursively process nested objects
162+
value = processJsonObject(value);
163+
}
164+
165+
result[newKey] = value;
166+
return result;
167+
}, {});
168+
};
169+
143170
try {
144171
const parsed = JSON.parse(content);
145-
return sortObjectKeys(parsed);
172+
const processedData = processJsonObject(parsed);
173+
log("Processed JSON data: removed underscores and flattened value objects");
174+
return sortObjectKeys(processedData);
146175
} catch (error) {
147176
log("Initial JSON parsing failed, attempting to wrap in array");
148177
try {
149178
const parsed = JSON.parse(`[${content}]`);
150-
return sortObjectKeys(parsed);
179+
const processedData = processJsonObject(parsed);
180+
log("Processed JSON data in array format");
181+
return sortObjectKeys(processedData);
151182
} catch (innerError) {
152183
console.error("JSON parsing error:", innerError);
153184
throw new Error(`Invalid JSON content: ${innerError.message}`);

src/localStorage.test.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,95 @@ test("parseJsonContent throws error for invalid JSON", () => {
3535
expect(() => parseJsonContent(invalidJson)).toThrow("Invalid JSON content");
3636
});
3737

38+
test("parseJsonContent removes underscores from keys", () => {
39+
const snakeCaseJson = JSON.stringify({
40+
snake_case_key: "value",
41+
normal_key: "value2",
42+
});
43+
44+
const result = parseJsonContent(snakeCaseJson);
45+
46+
expect(result).toHaveProperty("snakecasekey", "value");
47+
expect(result).toHaveProperty("normalkey", "value2");
48+
expect(result).not.toHaveProperty("snake_case_key");
49+
expect(result).not.toHaveProperty("normal_key");
50+
});
51+
52+
test("parseJsonContent removes underscores from deeply nested object keys", () => {
53+
const nestedJson = JSON.stringify({
54+
top_level: {
55+
nested_key: {
56+
deeply_nested_key: "value",
57+
},
58+
},
59+
});
60+
61+
const result = parseJsonContent(nestedJson);
62+
63+
expect(result).toHaveProperty("toplevel.nestedkey.deeplynestedkey", "value");
64+
expect(result).not.toHaveProperty("top_level");
65+
});
66+
67+
// New tests for value object flattening
68+
test("parseJsonContent flattens objects with a single 'value' property", () => {
69+
const valueObjectJson = JSON.stringify({
70+
normalKey: "normal",
71+
valueObject: { value: "flattened" },
72+
});
73+
74+
const result = parseJsonContent(valueObjectJson);
75+
76+
expect(result.normalKey).toBe("normal");
77+
expect(result.valueObject).toBe("flattened");
78+
expect(typeof result.valueObject).toBe("string");
79+
});
80+
81+
test("parseJsonContent flattens nested objects with a single 'value' property", () => {
82+
const nestedValueObjectJson = JSON.stringify({
83+
level1: {
84+
level2: {
85+
normalObj: { key: "value" },
86+
valueObj: { value: "flattened" },
87+
},
88+
},
89+
});
90+
91+
const result = parseJsonContent(nestedValueObjectJson);
92+
93+
expect(result.level1.level2.normalObj.key).toBe("value");
94+
expect(result.level1.level2.valueObj).toBe("flattened");
95+
expect(typeof result.level1.level2.valueObj).toBe("string");
96+
});
97+
98+
test("parseJsonContent handles both underscore removal and value flattening together", () => {
99+
const complexJson = JSON.stringify({
100+
snake_case: {
101+
nested_value_obj: { value: 123 },
102+
other_key: { some_nested: { value: "test" } },
103+
},
104+
});
105+
106+
const result = parseJsonContent(complexJson);
107+
108+
expect(result.snakecase.nestedvalueobj).toBe(123);
109+
expect(result.snakecase.otherkey.somenested).toBe("test");
110+
});
111+
112+
test("parseJsonContent properly handles arrays containing value objects", () => {
113+
const arrayWithValueObjects = JSON.stringify({
114+
items: [
115+
{ name: "item1", property: { value: 100 } },
116+
{ name: "item2", property: { value: 200 } },
117+
],
118+
});
119+
120+
const result = parseJsonContent(arrayWithValueObjects);
121+
122+
expect(result.items[0].name).toBe("item1");
123+
expect(result.items[0].property).toBe(100);
124+
expect(result.items[1].property).toBe(200);
125+
});
126+
38127
test("removeEmptyObjects removes empty nested objects", () => {
39128
const input = {
40129
a: {},

0 commit comments

Comments
 (0)