From f790b3a60a480ed99dac6f7301d8de22e6e4f61b Mon Sep 17 00:00:00 2001 From: Cindy Li Date: Tue, 16 Jun 2020 21:37:06 +0000 Subject: [PATCH 1/6] fix formatting, add directions functionality to map --- .../sps/SpsGuiceServletContextListener.java | 11 +- .../com/google/sps/data/LoginResponse.java | 6 +- .../GsonLoginResponseAdapter.java | 5 +- .../GsonLoginResponseSerializationModule.java | 1 - .../sps/servlets/DataDeleteServlet.java | 7 +- .../com/google/sps/servlets/DataServlet.java | 11 +- .../com/google/sps/servlets/LoginServlet.java | 11 +- portfolio/src/main/webapp/maps.html | 30 ++- portfolio/src/main/webapp/script.js | 217 ++++++++++++++++-- portfolio/src/main/webapp/style.css | 21 +- 10 files changed, 268 insertions(+), 52 deletions(-) diff --git a/portfolio/src/main/java/com/google/sps/SpsGuiceServletContextListener.java b/portfolio/src/main/java/com/google/sps/SpsGuiceServletContextListener.java index a418000..78599e7 100644 --- a/portfolio/src/main/java/com/google/sps/SpsGuiceServletContextListener.java +++ b/portfolio/src/main/java/com/google/sps/SpsGuiceServletContextListener.java @@ -4,10 +4,10 @@ import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.servlet.GuiceServletContextListener; -import com.google.sps.serialization.GsonLoginResponseSerializationModule; -import com.google.sps.servlets.ServletsModule; import com.google.sps.factory.DatastoreBindingModule; import com.google.sps.factory.UserServiceBindingModule; +import com.google.sps.serialization.GsonLoginResponseSerializationModule; +import com.google.sps.servlets.ServletsModule; /** * Provides an {@link Injector} configured to serve the SPS application routes. @@ -16,10 +16,7 @@ public class SpsGuiceServletContextListener extends GuiceServletContextListener { @Override protected Injector getInjector() { - return Guice.createInjector( - new DatastoreBindingModule(), - new UserServiceBindingModule(), - new GsonLoginResponseSerializationModule(), - new ServletsModule()); + return Guice.createInjector(new DatastoreBindingModule(), new UserServiceBindingModule(), + new GsonLoginResponseSerializationModule(), new ServletsModule()); } } diff --git a/portfolio/src/main/java/com/google/sps/data/LoginResponse.java b/portfolio/src/main/java/com/google/sps/data/LoginResponse.java index 3bc2da7..af307fb 100644 --- a/portfolio/src/main/java/com/google/sps/data/LoginResponse.java +++ b/portfolio/src/main/java/com/google/sps/data/LoginResponse.java @@ -16,18 +16,14 @@ import com.google.auto.value.AutoValue; - @AutoValue public abstract class LoginResponse { - public abstract String url(); public abstract boolean isLoggedIn(); public static Builder builder() { return new AutoValue_LoginResponse.Builder(); - } - - + } @AutoValue.Builder public static abstract class Builder { diff --git a/portfolio/src/main/java/com/google/sps/serialization/GsonLoginResponseAdapter.java b/portfolio/src/main/java/com/google/sps/serialization/GsonLoginResponseAdapter.java index 72ab6db..90fbd0e 100644 --- a/portfolio/src/main/java/com/google/sps/serialization/GsonLoginResponseAdapter.java +++ b/portfolio/src/main/java/com/google/sps/serialization/GsonLoginResponseAdapter.java @@ -14,16 +14,15 @@ package com.google.sps.serialization; -import com.google.sps.data.LoginResponse; import com.google.common.base.Strings; import com.google.gson.JsonParseException; import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; +import com.google.sps.data.LoginResponse; import java.io.IOException; - public class GsonLoginResponseAdapter extends TypeAdapter { private static final String LOGIN_RESPONSE_URL_JSON_FIELD_NAME = "url"; private static final String LOGIN_RESPONSE_IS_LOGGED_IN_JSON_FIELD_NAME = "isLoggedIn"; @@ -71,7 +70,7 @@ public void write(JsonWriter writer, LoginResponse loginResponse) throws IOExcep writer.name(LOGIN_RESPONSE_IS_LOGGED_IN_JSON_FIELD_NAME); writer.value(loginResponse.isLoggedIn()); - + writer.endObject(); } } diff --git a/portfolio/src/main/java/com/google/sps/serialization/GsonLoginResponseSerializationModule.java b/portfolio/src/main/java/com/google/sps/serialization/GsonLoginResponseSerializationModule.java index 06dd6bd..3b72dcb 100644 --- a/portfolio/src/main/java/com/google/sps/serialization/GsonLoginResponseSerializationModule.java +++ b/portfolio/src/main/java/com/google/sps/serialization/GsonLoginResponseSerializationModule.java @@ -7,7 +7,6 @@ import com.google.inject.Singleton; import com.google.sps.data.LoginResponse; - public class GsonLoginResponseSerializationModule extends AbstractModule { @Provides @Singleton diff --git a/portfolio/src/main/java/com/google/sps/servlets/DataDeleteServlet.java b/portfolio/src/main/java/com/google/sps/servlets/DataDeleteServlet.java index 235585e..6d386d4 100644 --- a/portfolio/src/main/java/com/google/sps/servlets/DataDeleteServlet.java +++ b/portfolio/src/main/java/com/google/sps/servlets/DataDeleteServlet.java @@ -23,6 +23,8 @@ import com.google.appengine.api.datastore.Query; import com.google.appengine.api.datastore.Query.SortDirection; import com.google.gson.Gson; +import com.google.inject.Inject; +import com.google.inject.Singleton; import com.google.sps.data.Comment; import java.io.IOException; import java.util.ArrayList; @@ -31,8 +33,6 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.google.inject.Singleton; -import com.google.inject.Inject; @Singleton public class DataDeleteServlet extends HttpServlet { @@ -46,7 +46,8 @@ public DataDeleteServlet(DatastoreService datastore, Gson gson) { } @Override - public void doDelete(HttpServletRequest request, HttpServletResponse response) throws IOException { + public void doDelete(HttpServletRequest request, HttpServletResponse response) + throws IOException { Query commentQuery = new Query("Comment"); PreparedQuery results = datastore.prepare(commentQuery); diff --git a/portfolio/src/main/java/com/google/sps/servlets/DataServlet.java b/portfolio/src/main/java/com/google/sps/servlets/DataServlet.java index 31ed2a8..513c0a2 100644 --- a/portfolio/src/main/java/com/google/sps/servlets/DataServlet.java +++ b/portfolio/src/main/java/com/google/sps/servlets/DataServlet.java @@ -21,6 +21,8 @@ import com.google.appengine.api.datastore.Query; import com.google.appengine.api.datastore.Query.SortDirection; import com.google.gson.Gson; +import com.google.inject.Inject; +import com.google.inject.Singleton; import com.google.sps.data.Comment; import java.io.IOException; import java.util.ArrayList; @@ -29,15 +31,13 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.google.inject.Singleton; -import com.google.inject.Inject; /** Servlet that returns some example content. TODO: modify this file to handle comments data */ @Singleton public class DataServlet extends HttpServlet { private final DatastoreService datastore; - private final Gson gson; - + private final Gson gson; + private static final String COMMENT_TEXT_PARAM = "comment"; private static final String COMMENT_NAME_PARAM = "name"; private static final String COMMENT_NUM_PARAM = "num-comments"; @@ -52,8 +52,6 @@ public DataServlet(DatastoreService datastore, Gson gson) { this.gson = gson; } - - @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { String comment = request.getParameter(COMMENT_TEXT_PARAM); @@ -75,7 +73,6 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) thr response.sendRedirect("/comments.html"); } - @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { int num_comments; diff --git a/portfolio/src/main/java/com/google/sps/servlets/LoginServlet.java b/portfolio/src/main/java/com/google/sps/servlets/LoginServlet.java index fa81a66..9bd8993 100644 --- a/portfolio/src/main/java/com/google/sps/servlets/LoginServlet.java +++ b/portfolio/src/main/java/com/google/sps/servlets/LoginServlet.java @@ -14,19 +14,19 @@ package com.google.sps.servlets; -import com.google.sps.serialization.GsonLoginResponseAdapter; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory; -import com.google.sps.data.LoginResponse; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import com.google.sps.data.LoginResponse; +import com.google.sps.serialization.GsonLoginResponseAdapter; import java.io.IOException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.google.inject.Singleton; -import com.google.inject.Inject; @Singleton public class LoginServlet extends HttpServlet { @@ -41,11 +41,10 @@ public LoginServlet(UserService userService, Gson gson) { this.gson = gson; } - @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { /** - * remove this builder once this uses Guice + * remove this builder once this uses Guice */ GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(LoginResponse.class, new GsonLoginResponseAdapter()); diff --git a/portfolio/src/main/webapp/maps.html b/portfolio/src/main/webapp/maps.html index fff71c1..d855d6e 100644 --- a/portfolio/src/main/webapp/maps.html +++ b/portfolio/src/main/webapp/maps.html @@ -2,7 +2,7 @@ Map - + @@ -17,7 +17,33 @@

My Notable Locations

-
+
+ + +
+ + + + +
+ + + + + + + + +
+
+ +
+
diff --git a/portfolio/src/main/webapp/script.js b/portfolio/src/main/webapp/script.js index e59bba2..0506bec 100644 --- a/portfolio/src/main/webapp/script.js +++ b/portfolio/src/main/webapp/script.js @@ -57,10 +57,10 @@ async function setPage() { const loginJson = await loginResponse.json(); addLogInOutButton(loginJson.url, loginJson.isLoggedIn); - const customContainer = document.getElementById("custom-elements"); - const formContainer = document.getElementById("comment-form"); + const customContainer = document.getElementById('custom-elements'); + const formContainer = document.getElementById('comment-form'); - if (loginJson.isLoggedIn) { + if (loginJson.isLoggedIn) { shouldHideElement(customContainer, false); shouldHideElement(formContainer, false); setComments(); @@ -84,12 +84,13 @@ async function setComments() { num_comments = document.getElementById('num-comments').value; order = document.getElementById('order').value; - const response = await fetch('/data?num-comments=' + num_comments + '&order=' + order); + const response = + await fetch('/data?num-comments=' + num_comments + '&order=' + order); if (response.ok) { const responseJson = await response.json(); for (let i = 0; i < responseJson.length; i++) { - commentContainer.appendChild(createListComment(responseJson[i])); + commentContainer.appendChild(createListComment(responseJson[i])); } } else { @@ -137,7 +138,6 @@ function addLogInOutButton(url, isLoggedIn) { } else { button.innerText = 'Log In'; } - } function shouldHideElement(container, hide) { @@ -148,25 +148,210 @@ function shouldHideElement(container, hide) { } } +let map; function initMap() { const tokyo = {lat: 35.668, lng: 139.723}; const hachi = {lat: 35.659107, lng: 139.700653}; - const map = new google.maps.Map(document.getElementById('map'), { - center: tokyo, - zoom: 12 - }); + map = new google.maps.Map( + document.getElementById('map'), + {center: tokyo, zoom: 12, mapTypeControl: false}); const marker = new google.maps.Marker({position: hachi, map: map}) - hachiString = '

Statue of Hachiko

' + - '

a very good boi

' + - '

For actual info on Hachiko, visit his' + - ' Wikipedia page ' + - '

'; + hachiString = '

Statue of Hachiko

' + + '

a very good boi

' + + '

For actual info on Hachiko, visit his' + + ' Wikipedia page ' + + '

'; var infowindow = new google.maps.InfoWindow({content: hachiString}); marker.addListener('click', function() { infowindow.open(map, marker); - }) + }); + + new AutocompleteDirectionsHandler(map); +} + +function addMarker() { + const shouldAddMarker = document.getElementById('add-marker').value + console.log(shouldAddMarker) + + if (shouldAddMarker === 'true') { + console.log('here'); + map.addListener('click', function(mapsMouseEvent) { + const newMarker = + new google.maps.Marker({position: mapsMouseEvent.latLng, map: map}); + }); + } + else { + google.maps.event.clearListeners(map, 'click'); + } +} + +// START OF DIRECTIONS CODE + +// This example requires the Places library. Include the libraries=places +// parameter when you first load the API. For example: +// + diff --git a/portfolio/src/main/webapp/script.js b/portfolio/src/main/webapp/script.js index 1e25853..cf533e7 100644 --- a/portfolio/src/main/webapp/script.js +++ b/portfolio/src/main/webapp/script.js @@ -154,7 +154,7 @@ function initMap() { const hachi = {lat: 35.659107, lng: 139.700653}; map = new google.maps.Map( document.getElementById('map'), - {center: tokyo, zoom: 12, mapTypeControl: false}); + {center: tokyo, zoom: 12}); const marker = new google.maps.Marker({position: hachi, map: map}) @@ -229,10 +229,11 @@ function AutocompleteDirectionsHandler(map) { this.setupPlaceChangedListener(originAutocomplete, 'ORIG'); this.setupPlaceChangedListener(destinationAutocomplete, 'DEST'); - this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(originInput); - this.map.controls[google.maps.ControlPosition.TOP_LEFT].push( + this.map.controls[google.maps.ControlPosition.TOP_RIGHT].push(modeSelector); + this.map.controls[google.maps.ControlPosition.TOP_RIGHT].push( destinationInput); - this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(modeSelector); + this.map.controls[google.maps.ControlPosition.TOP_RIGHT].push(originInput); + } // Sets a listener on a radio button to change the filter type on Places diff --git a/portfolio/src/main/webapp/style.css b/portfolio/src/main/webapp/style.css index 7440b0e..b9a9773 100644 --- a/portfolio/src/main/webapp/style.css +++ b/portfolio/src/main/webapp/style.css @@ -215,7 +215,7 @@ textarea { .controls { margin-top: 10px; - margin-left: 5px; + margin-right: 5px; height: 32px; } From 8b2b946a0d84ec0c2966157aadb7d53da1e9c968 Mon Sep 17 00:00:00 2001 From: Cindy Li Date: Wed, 17 Jun 2020 16:43:25 +0000 Subject: [PATCH 4/6] added written directions, moved navbar to the front --- portfolio/src/main/webapp/maps.html | 3 ++- portfolio/src/main/webapp/script.js | 3 +++ portfolio/src/main/webapp/style.css | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/portfolio/src/main/webapp/maps.html b/portfolio/src/main/webapp/maps.html index 7be2be7..860e758 100644 --- a/portfolio/src/main/webapp/maps.html +++ b/portfolio/src/main/webapp/maps.html @@ -23,7 +23,7 @@

My Notable Locations

-
+
@@ -43,6 +43,7 @@

My Notable Locations

+
diff --git a/portfolio/src/main/webapp/script.js b/portfolio/src/main/webapp/script.js index cf533e7..51e1630 100644 --- a/portfolio/src/main/webapp/script.js +++ b/portfolio/src/main/webapp/script.js @@ -212,6 +212,9 @@ function AutocompleteDirectionsHandler(map) { var originInput = document.getElementById('origin-input'); var destinationInput = document.getElementById('destination-input'); var modeSelector = document.getElementById('mode-selector'); + var directionsSteps = document.getElementById('directions'); + + this.directionsRenderer.setPanel(directionsSteps); var originAutocomplete = new google.maps.places.Autocomplete(originInput); // Specify just the place data fields that you need. diff --git a/portfolio/src/main/webapp/style.css b/portfolio/src/main/webapp/style.css index b9a9773..1a11083 100644 --- a/portfolio/src/main/webapp/style.css +++ b/portfolio/src/main/webapp/style.css @@ -57,6 +57,7 @@ body { width: 100%; position: fixed; top: 0; + z-index: 1; } .nav a { @@ -209,7 +210,7 @@ textarea { margin: 20px; } -#directions { +#directions-section { display: none; } From 3e1537b3b65256fee30e99355cb54856a512cd82 Mon Sep 17 00:00:00 2001 From: Cindy Li Date: Thu, 18 Jun 2020 19:59:29 +0000 Subject: [PATCH 5/6] fix functionality, can now go back and forth between autofill and typing --- portfolio/src/main/webapp/script.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/portfolio/src/main/webapp/script.js b/portfolio/src/main/webapp/script.js index 1c9e9b4..22c77a5 100644 --- a/portfolio/src/main/webapp/script.js +++ b/portfolio/src/main/webapp/script.js @@ -311,8 +311,10 @@ AutocompleteDirectionsHandler.prototype.setupPlaceChangedListener = function( if (status === google.maps.places.PlacesServiceStatus.OK) { if (mode === 'ORIG') { me.originPlace = results[0]; + me.originPlaceId = null; } else { me.destinationPlace = results[0]; + me.destinationPlaceId = null; } me.route(); @@ -322,8 +324,10 @@ AutocompleteDirectionsHandler.prototype.setupPlaceChangedListener = function( } else { if (mode === 'ORIG') { me.originPlaceId = place.place_id; + me.originPlace = null; } else { me.destinationPlaceId = place.place_id; + me.destinationPlace = null; } me.route(); } @@ -341,6 +345,7 @@ AutocompleteDirectionsHandler.prototype.route = if (!this.originPlace) { if (!this.originPlaceId) { + console.log("here") return; } else { originVal = getProperPlaceVal(this.originPlaceId, true); @@ -359,6 +364,9 @@ AutocompleteDirectionsHandler.prototype.route = destinationVal = getProperPlaceVal(this.destinationPlace, false); } + console.log(originVal); + console.log(destinationVal); + this.directionsService.route( { origin: originVal, From 62ad3e609a4c624af812b6b16a35b3015dfb0f53 Mon Sep 17 00:00:00 2001 From: Cindy Li Date: Fri, 19 Jun 2020 18:58:23 +0000 Subject: [PATCH 6/6] simplify directions by getting place_id --- portfolio/src/main/webapp/script.js | 79 +++++++++-------------------- 1 file changed, 23 insertions(+), 56 deletions(-) diff --git a/portfolio/src/main/webapp/script.js b/portfolio/src/main/webapp/script.js index 22c77a5..3859b23 100644 --- a/portfolio/src/main/webapp/script.js +++ b/portfolio/src/main/webapp/script.js @@ -233,8 +233,6 @@ function AutocompleteDirectionsHandler(map) { this.map = map; this.originPlaceId = null; this.destinationPlaceId = null; - this.originPlace = null; - this.destinationPlace = null; this.travelMode = 'WALKING'; this.directionsService = new google.maps.DirectionsService; this.directionsRenderer = new google.maps.DirectionsRenderer; @@ -304,73 +302,50 @@ AutocompleteDirectionsHandler.prototype.setupPlaceChangedListener = function( var request = { query: placeText, - fields: ['name', 'geometry'], + fields: ['place_id'], }; + var placeId; + service.findPlaceFromQuery(request, function(results, status) { if (status === google.maps.places.PlacesServiceStatus.OK) { - if (mode === 'ORIG') { - me.originPlace = results[0]; - me.originPlaceId = null; + if (mode === 'ORIG') { + me.originPlaceId = results[0].place_id; } else { - me.destinationPlace = results[0]; - me.destinationPlaceId = null; + me.destinationPlaceId = results[0].place_id; } - - me.route(); - return; } + + me.route(); }); + return; + } + + if (mode === 'ORIG') { + me.originPlaceId = place.place_id; } else { - if (mode === 'ORIG') { - me.originPlaceId = place.place_id; - me.originPlace = null; - } else { - me.destinationPlaceId = place.place_id; - me.destinationPlace = null; - } - me.route(); + me.destinationPlaceId = place.place_id; } + me.route(); }); }; -AutocompleteDirectionsHandler.prototype.route = - function() { - +AutocompleteDirectionsHandler.prototype.route = function() { var me = this; - let originVal; - let destinationVal; - - if (!this.originPlace) { - if (!this.originPlaceId) { - console.log("here") - return; - } else { - originVal = getProperPlaceVal(this.originPlaceId, true); - } - } else { - originVal = getProperPlaceVal(this.originPlace, false); + if (!this.originPlaceId) { + return; } - - if (!this.destinationPlace) { - if (!this.destinationPlaceId) { - return; - } else { - destinationVal = getProperPlaceVal(this.destinationPlaceId, true); - } - } else { - destinationVal = getProperPlaceVal(this.destinationPlace, false); + + if (!this.destinationPlaceId) { + return; } - console.log(originVal); - console.log(destinationVal); - this.directionsService.route( { - origin: originVal, - destination: destinationVal, + origin: {'placeId': this.originPlaceId}, + destination: {'placeId': this.destinationPlaceId}, travelMode: this.travelMode }, function(response, status) { @@ -383,11 +358,3 @@ AutocompleteDirectionsHandler.prototype.route = ); } - -function getProperPlaceVal(locationVal, isId) { - if (isId) { - return {'placeId': locationVal}; - } else { - return locationVal.name; - } -}