diff --git a/app/assets/javascripts/user.js b/app/assets/javascripts/user.js index f3fe02e0c..7d90fd119 100644 --- a/app/assets/javascripts/user.js +++ b/app/assets/javascripts/user.js @@ -8,9 +8,19 @@ $(function () { const defaultHomeZoom = 12; - let map, marker, deleted_lat, deleted_lon; + let map, marker, deleted_lat, deleted_lon, savedLat, savedLon, locationInput; if ($("#map").length) { + savedLat = $("#home_lat").val(); + savedLon = $("#home_lon").val(); + locationInput = { + dirty: false, + requestController: null, + countryName: $("#location_name").val().trim(), + deletedText: null, + checkLocation: savedLat && savedLon && $("#location_name").val().trim() + }; + map = L.map("map", { attributionControl: false, zoomControl: false @@ -69,8 +79,7 @@ $(function () { $("#home_lat").val(lat); $("#home_lon").val(lon); - deleted_lat = null; - deleted_lon = null; + clearDeletedText(); respondToHomeUpdate(); }).on("moveend", function () { const lat = $("#home_lat").val().trim(), @@ -89,11 +98,17 @@ $(function () { }); $("#home_lat, #home_lon").on("input", function () { - deleted_lat = null; - deleted_lon = null; + clearDeletedText(); respondToHomeUpdate(); }); + $("#location_name").on("input", function () { + locationInput.dirty = true; + clearDeletedText(); + + respondToHomeUpdate(false); + }); + $("#home_show").click(function () { const lat = $("#home_lat").val(), lon = $("#home_lon").val(); @@ -103,21 +118,25 @@ $(function () { $("#home_delete").click(function () { const lat = $("#home_lat").val(), - lon = $("#home_lon").val(); + lon = $("#home_lon").val(), + locationName = $("#location_name").val(); - $("#home_lat, #home_lon").val(""); + $("#home_lat, #home_lon, #location_name").val(""); deleted_lat = lat; deleted_lon = lon; - respondToHomeUpdate(); + locationInput.deletedText = locationName; + + respondToHomeUpdate(false); $("#home_undelete").trigger("focus"); }); $("#home_undelete").click(function () { $("#home_lat").val(deleted_lat); $("#home_lon").val(deleted_lon); - deleted_lat = null; - deleted_lon = null; - respondToHomeUpdate(); + $("#location_name").val(locationInput.deletedText); + clearDeletedText(); + + respondToHomeUpdate(false); $("#home_delete").trigger("focus"); }); } else { @@ -131,14 +150,22 @@ $(function () { } } - function respondToHomeUpdate() { + function respondToHomeUpdate(updateLocationName = true) { const lat = $("#home_lat").val().trim(), - lon = $("#home_lon").val().trim(); + lon = $("#home_lon").val().trim(), + locationName = $("#location_name").val().trim(); let location; try { if (lat && lon) { location = L.latLng(lat, lon); + if (updateLocationName) { + if (locationInput.checkLocation) { + updateHomeLocation(false, savedLat, savedLon, updateHomeLocation); + } else { + updateHomeLocation(); + } + } } $("#home_lat, #home_lon").removeClass("is-invalid"); } catch (error) { @@ -148,8 +175,11 @@ $(function () { $("#home_message").toggleClass("invisible", Boolean(location)); $("#home_show").prop("hidden", !location); - $("#home_delete").prop("hidden", !location); - $("#home_undelete").prop("hidden", !(!location && deleted_lat && deleted_lon)); + $("#home_delete").prop("hidden", !location && !locationName); + $("#home_undelete").prop("hidden", !( + (!location || !locationName) && + ((deleted_lat && deleted_lon) || locationInput.deletedText) + )); if (location) { marker.setLatLng([lat, lon]); marker.addTo(map); @@ -176,6 +206,64 @@ $(function () { } } + function updateHomeLocation(updateInput = true, lat = $("#home_lat").val().trim(), lon = $("#home_lon").val().trim(), successFn) { + if (!lat || !lon || locationInput.dirty) { + return; + } + + const geocodeUrl = "/geocoder/search_osm_nominatim_reverse", + csrf_param = $("meta[name=csrf-param]").attr("content"), + csrf_token = $("meta[name=csrf-token]").attr("content"), + params = new URLSearchParams({ + lat, + lon, + zoom: 3 + }); + params.set(csrf_param, csrf_token); + + if (locationInput.requestController) { + locationInput.requestController.abort(); + } + + const requestController = new AbortController(); + locationInput.requestController = requestController; + fetch(geocodeUrl, { + method: "POST", + body: params, + signal: locationInput.requestController.signal, + headers: { accept: "application/json" } + }) + .then(response => response.json()) + .then((data) => { + const country = data.length ? data[0].name : ""; + + if (updateInput) { + $("#location_name").val(country); + } else { + locationInput.checkLocation = false; + if (locationInput.countryName !== country) { + locationInput.dirty = true; + } + } + locationInput.countryName = country; + locationInput.requestController = null; + + if (successFn) { + successFn(); + } + }).catch(() => { + if (location.requestController === requestController) { + locationInput.requestController = null; + } + }); + } + + function clearDeletedText() { + deleted_lat = null; + deleted_lon = null; + locationInput.deletedText = null; + } + updateAuthUID(); $("select#user_auth_provider").on("change", updateAuthUID); diff --git a/app/controllers/geocoder_controller.rb b/app/controllers/geocoder_controller.rb index 5f3b4dbb6..035f4b2ff 100644 --- a/app/controllers/geocoder_controller.rb +++ b/app/controllers/geocoder_controller.rb @@ -152,7 +152,11 @@ class GeocoderController < ApplicationController :type => object_type, :id => object_id) end - render :action => "results" + respond_to do |format| + format.html { render :action => "results" } + format.json { render :json => @results } + format.any { render :action => "results" } + end rescue StandardError => e host = URI(Settings.nominatim_url).host @error = "Error contacting #{host}: #{e}" diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 4005176ce..99d9d0e13 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -31,6 +31,7 @@ class ProfilesController < ApplicationController current_user.home_lat = params[:user][:home_lat] current_user.home_lon = params[:user][:home_lon] + current_user.location_name = params[:user][:location_name] if current_user.save flash[:notice] = t ".success" diff --git a/app/models/user.rb b/app/models/user.rb index a63846e42..b4cf01eac 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -12,6 +12,7 @@ # home_lat :float # home_lon :float # home_zoom :integer default(3) +# location_name :string # pass_salt :string # email_valid :boolean default(FALSE), not null # new_email :string diff --git a/app/views/profiles/edit.html.erb b/app/views/profiles/edit.html.erb index ac76b4d2d..373ae5290 100644 --- a/app/views/profiles/edit.html.erb +++ b/app/views/profiles/edit.html.erb @@ -52,6 +52,7 @@ + <%= f.text_field :location_name, :wrapper_class => "my-2 col-sm-4 pe-3", :class => "mt-auto", :id => "location_name" %>