Skip to content

Commit 1d2b0a8

Browse files
authored
Json editor and other cleanup (#36)
* separate algo editing into add,edit,delete buttons * add basic alerts when server returns errors * move seed algos to its own json data file * only enable OK button after syntax checking is done and no errors are found * remove old seed algo data
1 parent d63cb9c commit 1d2b0a8

File tree

8 files changed

+257
-179
lines changed

8 files changed

+257
-179
lines changed

public/seedAlgos.json

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
{
2+
"rp": {
3+
"name": "Routes Preferred - traffic unaware",
4+
"numRoutes": 100,
5+
"api": "RoutesPreferred",
6+
"travelMode": "DRIVE",
7+
"routingPreference": "TRAFFIC_UNAWARE"
8+
},
9+
"rp_traffic_aware": {
10+
"name": "Route Preferred - traffic aware",
11+
"numRoutes": 100,
12+
"api": "RoutesPreferred",
13+
"travelMode": "DRIVE",
14+
"routingPreference": "TRAFFIC_AWARE"
15+
},
16+
"rp_traffic_aware_optimal": {
17+
"name": "Route Preferred - traffic aware optimal",
18+
"numRoutes": 100,
19+
"api": "RoutesPreferred",
20+
"travelMode": "DRIVE",
21+
"routingPreference": "TRAFFIC_AWARE_OPTIMAL"
22+
},
23+
"rp_bicycle": {
24+
"name": "Route Preferred - bicycle",
25+
"numRoutes": 100,
26+
"api": "RoutesPreferred",
27+
"travelMode": "BICYCLE"
28+
},
29+
"rp_twowheeler": {
30+
"name": "Route Preferred - two wheeler",
31+
"numRoutes": 100,
32+
"api": "RoutesPreferred",
33+
"travelMode": "TWO_WHEELER"
34+
},
35+
"rp_avoid_highway": {
36+
"name": "Route Preferred - avoid highway",
37+
"numRoutes": 100,
38+
"api": "RoutesPreferred",
39+
"travelMode": "DRIVE",
40+
"routingPreference": "TRAFFIC_AWARE",
41+
"options": {
42+
"avoidHighways": true
43+
}
44+
},
45+
"rp_avoid_tolls": {
46+
"name": "Route Preferred - avoid tolls",
47+
"numRoutes": 100,
48+
"api": "RoutesPreferred",
49+
"travelMode": "DRIVE",
50+
"routingPreference": "TRAFFIC_AWARE",
51+
"options": {
52+
"avoidTolls": true
53+
}
54+
},
55+
"rp_25_waypoints": {
56+
"name": "Route Preferred - 25 waypoints",
57+
"numRoutes": 1,
58+
"numWaypoints": 25,
59+
"api": "RoutesPreferred",
60+
"travelMode": "DRIVE",
61+
"routingPreference": "TRAFFIC_AWARE"
62+
},
63+
"directions_25_waypoints": {
64+
"name": "Directions - 25 waypoints",
65+
"numRoutes": 1,
66+
"numWaypoints": 25,
67+
"api": "DirectionsJsSDK",
68+
"travelMode": "DRIVING"
69+
},
70+
"directions_25_waypoints_optimized": {
71+
"name": "Directions - 25 waypoints (optimized)",
72+
"numRoutes": 1,
73+
"numWaypoints": 25,
74+
"api": "DirectionsJsSDK",
75+
"travelMode": "DRIVING",
76+
"options": {
77+
"optimizeWaypoints": true
78+
}
79+
},
80+
"directions": {
81+
"name": "Directions - Driving",
82+
"numRoutes": 15,
83+
"api": "DirectionsJsSDK",
84+
"travelMode": "DRIVING"
85+
},
86+
"directions_bicycle": {
87+
"name": "Directions - Bike",
88+
"numRoutes": 15,
89+
"api": "DirectionsJsSDK",
90+
"travelMode": "BICYCLING"
91+
},
92+
"directions_avoid_highway": {
93+
"name": "Directions - Avoid Highways",
94+
"numRoutes": 15,
95+
"api": "DirectionsJsSDK",
96+
"travelMode": "DRIVING",
97+
"options": {
98+
"avoidHighways": true
99+
}
100+
},
101+
"directions_avoid_tolls": {
102+
"name": "Directions - Avoid Tolls",
103+
"numRoutes": 15,
104+
"api": "DirectionsJsSDK",
105+
"travelMode": "DRIVING",
106+
"options": {
107+
"avoidTolls": true
108+
}
109+
}
110+
}

src/App.js

+37-10
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import "react-loader-spinner/dist/loader/css/react-spinner-loader.css";
2828
import Select from "react-select";
2929

3030
import { GetRoutes } from "./dataModel/algoFns";
31-
import { seedAlgos, addOrUpdateAlgo } from "./dataModel/algoModel";
31+
import { addAlgo, updateAlgo, deleteAlgo } from "./dataModel/algoModel";
3232
import { metroOptions } from "./dataModel/data";
3333
import JsonEditor from "./JsonEditor";
3434
import Map from "./Map";
@@ -54,14 +54,11 @@ class App extends React.Component {
5454
return defaultSelection;
5555
}
5656

57-
let allAlgos = seedAlgos();
57+
let allAlgos = { ...props.algos };
5858
let selectedAlgoId = Object.keys(allAlgos)[0];
5959
const urlAlgoStr = getQueryStringValue("algo");
6060
if (urlAlgoStr) {
61-
const { id, newAlgos } = addOrUpdateAlgo(
62-
allAlgos,
63-
JSON.parse(urlAlgoStr)
64-
);
61+
const { id, newAlgos } = addAlgo(allAlgos, JSON.parse(urlAlgoStr));
6562
allAlgos = newAlgos;
6663
selectedAlgoId = id;
6764
}
@@ -73,6 +70,7 @@ class App extends React.Component {
7370
showSpinner: true,
7471
regenData: false,
7572
showEditor: false,
73+
editMode: "add",
7674
chartData: {
7775
latencyData: [],
7876
durationData: [],
@@ -122,14 +120,37 @@ class App extends React.Component {
122120
this.setState({ showSpinner: true, regenData: true });
123121
};
124122

125-
this.openEditor = () => {
126-
this.setState({ showEditor: true });
123+
this.openEditor = (mode) => {
124+
this.setState({ showEditor: true, editMode: mode });
127125
};
128126

129127
this.closeEditor = () => {
130128
this.setState({ showEditor: false });
131129
};
132130

131+
this.deleteSelectedOption = () => {
132+
// Avoid the scenario where we would have empty algos
133+
if (Object.keys(this.state.algos).length <= 1) return;
134+
135+
const { newAlgos } = deleteAlgo(
136+
this.state.algos,
137+
this.state.selectedAlgoId
138+
);
139+
const defaultId = Object.keys(newAlgos)[0];
140+
this.setState(
141+
{
142+
algos: newAlgos,
143+
selectedAlgoId: defaultId,
144+
},
145+
() => {
146+
setQueryStringValue(
147+
"algo",
148+
JSON.stringify(this.state.algos[this.state.selectedAlgoId])
149+
);
150+
}
151+
);
152+
};
153+
133154
this.submitJson = (content) => {
134155
// TODO: Perform more validation
135156
if (
@@ -142,7 +163,11 @@ class App extends React.Component {
142163
return;
143164
}
144165

145-
const { id, newAlgos } = addOrUpdateAlgo(this.state.algos, content);
166+
const { id, newAlgos } =
167+
this.state.editMode == "add"
168+
? addAlgo(this.state.algos, content)
169+
: updateAlgo(this.state.algos, this.state.selectedAlgoId, content);
170+
146171
this.setState(
147172
{
148173
showEditor: false,
@@ -217,7 +242,9 @@ class App extends React.Component {
217242
onChange={this.handleAlgoChange}
218243
options={selectAlgoOptions}
219244
/>
220-
<button onClick={this.openEditor}>Add or update...</button>
245+
<button onClick={() => this.openEditor("add")}>Add</button>
246+
<button onClick={() => this.openEditor("edit")}>Edit</button>
247+
<button onClick={this.deleteSelectedOption}>Delete</button>
221248
<Select
222249
value={this.state.selectedMetroOption}
223250
onChange={this.handleMetroChange}

src/JsonEditor.js

+23-11
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,36 @@ import ReactModal from "react-modal";
2727

2828
function JsonEditor({ isOpen, initialJson, onSubmit, onCancel }) {
2929
const [jsonContent, setJsonContent] = useState(initialJson);
30+
const [enableSubmit, setEnableSubmit] = useState(true);
31+
32+
function handleKeyDown() {
33+
setEnableSubmit(false);
34+
}
3035

3136
function onJsonChange(content) {
32-
setJsonContent(content.jsObject);
37+
if (!content.error) {
38+
setJsonContent(content.jsObject);
39+
setEnableSubmit(true);
40+
}
3341
}
3442

3543
return (
3644
<ReactModal isOpen={isOpen} contentLabel="Editor dialog">
37-
<JSONInput
38-
locale={locale}
39-
placeholder={initialJson}
40-
waitAfterKeyPress={2000}
41-
theme={"light_mitsuketa_tribute"}
42-
colors={{ default: "#888888" }}
43-
style={{ body: { fontSize: "16px" } }}
44-
onChange={onJsonChange}
45-
/>
45+
<div onKeyDown={handleKeyDown}>
46+
<JSONInput
47+
locale={locale}
48+
placeholder={initialJson}
49+
waitAfterKeyPress={2000}
50+
theme={"light_mitsuketa_tribute"}
51+
colors={{ default: "#888888" }}
52+
style={{ body: { fontSize: "16px" } }}
53+
onChange={onJsonChange}
54+
/>
55+
</div>
4656
<button onClick={onCancel}>Cancel</button>
47-
<button onClick={() => onSubmit(jsonContent)}>OK</button>
57+
<button disabled={!enableSubmit} onClick={() => onSubmit(jsonContent)}>
58+
OK
59+
</button>
4860
</ReactModal>
4961
);
5062
}

src/Map.js

-8
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,6 @@ function MyMapComponent({
5858
}) {
5959
const ref = useRef();
6060

61-
/*
62-
* Handler for timewindow change. Updates global min/max date globals
63-
* and recomputes the paths as well as all the bubble markers to respect the
64-
* new date values.
65-
*
66-
* Debounced to every 100ms as a blance between performance and reactivity when
67-
* the slider is dragged.
68-
*/
6961
const onStateChangeDebounced = debounce(async (regenerate = false) => {
7062
if (!window.google) {
7163
// not loaded yet?

src/apis/directionsJsSDK.js

+16-11
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,22 @@ async function computeRoutesDirectionsJsSDK(pairs, travelMode, options = {}) {
5757
let pair;
5858
let paths = [];
5959
while ((pair = pairs.shift())) {
60-
const result = await calcRoute(
61-
pair.origin,
62-
pair.destination,
63-
pair.waypoints,
64-
travelMode,
65-
options
66-
);
67-
await new Promise((r) => setTimeout(r, 400));
68-
if (result) {
69-
// sometimes there aren't routes
70-
paths.push(result);
60+
try {
61+
const result = await calcRoute(
62+
pair.origin,
63+
pair.destination,
64+
pair.waypoints,
65+
travelMode,
66+
options
67+
);
68+
await new Promise((r) => setTimeout(r, 400));
69+
if (result) {
70+
// sometimes there aren't routes
71+
paths.push(result);
72+
}
73+
} catch (err) {
74+
alert(`${err.name}: ${err.message}`);
75+
return paths;
7176
}
7277
}
7378
return paths;

src/apis/routesPreferred.js

+17-18
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,7 @@ async function calcRoute(
7777
},
7878
};
7979

80-
let result;
81-
try {
82-
result = await axios(config);
83-
} catch (err) {
84-
console.log("failed", err);
85-
return;
86-
}
80+
const result = await axios(config);
8781
const timeAfter = Date.now();
8882
if (result.data.routes) {
8983
// sometimes no route returned
@@ -101,17 +95,22 @@ async function computeRoutesPreferred(
10195
let pair;
10296
let paths = [];
10397
while ((pair = pairs.shift())) {
104-
const result = await calcRoute(
105-
pair.origin,
106-
pair.destination,
107-
pair.waypoints,
108-
travelMode,
109-
routingPreference,
110-
options
111-
);
112-
if (result) {
113-
// sometimes there aren't routes
114-
paths.push(result);
98+
try {
99+
const result = await calcRoute(
100+
pair.origin,
101+
pair.destination,
102+
pair.waypoints,
103+
travelMode,
104+
routingPreference,
105+
options
106+
);
107+
if (result) {
108+
// sometimes there aren't routes
109+
paths.push(result);
110+
}
111+
} catch (err) {
112+
alert(`Server error: ${err.message}`);
113+
return paths;
115114
}
116115
}
117116
return paths;

0 commit comments

Comments
 (0)