mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-11 23:17:48 +00:00
Get registration location map working with OSM
This commit is contained in:
committed by
zanetagebka
parent
f4a69b4664
commit
87fe5f413b
@@ -42,8 +42,17 @@ angular.module('Darkswarm').controller "RegistrationCtrl", ($scope, Registration
|
||||
$scope.toggleAddressConfirmed = ->
|
||||
$scope.addressConfirmed = !$scope.addressConfirmed
|
||||
if $scope.addressConfirmed
|
||||
$scope.setLatLongIfUsingOpenStreetMap()
|
||||
$scope.enterprise.address.latitude = $scope.latLong.latitude
|
||||
$scope.enterprise.address.longitude = $scope.latLong.longitude
|
||||
else
|
||||
$scope.enterprise.address.latitude = null
|
||||
$scope.enterprise.address.longitude = null
|
||||
|
||||
# When OpenStreetMaps is enabled the latitude and longitude are calculated via a Stimulus
|
||||
# controller, so they need to be read from data properties to be accessible here.
|
||||
$scope.setLatLongIfUsingOpenStreetMap = ->
|
||||
openStreetMap = document.getElementById("open-street-map")
|
||||
if !$scope.latLong && openStreetMap && openStreetMap.dataset.latitude && openStreetMap.dataset.longitude
|
||||
$scope.latLong = { latitude: openStreetMap.dataset.latitude, longitude: openStreetMap.dataset.longitude }
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
module MapHelper
|
||||
def using_google_maps?
|
||||
ENV["GOOGLE_MAPS_API_KEY"].present? || google_maps_configured_with_geocoder_api_key?
|
||||
!ContentConfig.open_street_map_enabled && (
|
||||
ENV["GOOGLE_MAPS_API_KEY"].present? || google_maps_configured_with_geocoder_api_key?
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -57,7 +57,10 @@
|
||||
%span.error{ "ng-show": "details.state.$error.required && submitted" }
|
||||
= t(".state_field_error")
|
||||
|
||||
= render 'registration/steps/location_map' if using_google_maps?
|
||||
- if using_google_maps?
|
||||
= render 'registration/steps/location_map_google'
|
||||
- elsif ContentConfig.open_street_map_enabled
|
||||
= render 'registration/steps/location_map_osm'
|
||||
|
||||
.row.buttons
|
||||
.small-12.columns
|
||||
|
||||
18
app/views/registration/steps/_location_map_osm.html.haml
Normal file
18
app/views/registration/steps/_location_map_osm.html.haml
Normal file
@@ -0,0 +1,18 @@
|
||||
%div{ data: {
|
||||
controller: "open-street-map",
|
||||
"open-street-map-default-latitude-value": ContentConfig.open_street_map_default_latitude,
|
||||
"open-street-map-default-longitude-value": ContentConfig.open_street_map_default_longitude,
|
||||
"open-street-map-provider-name-value": ContentConfig.open_street_map_provider_name,
|
||||
"open-street-map-provider-options-value": ContentConfig.open_street_map_provider_options
|
||||
}
|
||||
}
|
||||
.center
|
||||
%input.button.primary{ data: { action: "click->open-street-map#locateAddress" }, type: "button", value: "{{'registration.steps.details.locate_address' | t}}" }
|
||||
.center{ data: { "open-street-map-target": "dragPinNote" }, style: "display: none" }
|
||||
%strong {{'registration.steps.details.drag_pin' | t}}
|
||||
#open-street-map.map-container--registration
|
||||
|
||||
.center{ data: { "open-street-map-target": "confirmAddressField" }, style: "display: none" }
|
||||
.field
|
||||
%input{ type: 'checkbox', id: 'confirm_address', name: 'confirm_address', "ng-click": 'toggleAddressConfirmed()' }
|
||||
%label{ for: 'confirm_address' } {{'registration.steps.details.confirm_address' | t}}
|
||||
103
app/webpacker/controllers/open_street_map_controller.js
Normal file
103
app/webpacker/controllers/open_street_map_controller.js
Normal file
@@ -0,0 +1,103 @@
|
||||
import { Controller } from "stimulus";
|
||||
import L from "leaflet";
|
||||
import LeafetProviders from "leaflet-providers";
|
||||
import { OpenStreetMapProvider } from 'leaflet-geosearch';
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["confirmAddressField", "dragPinNote"];
|
||||
static values = {
|
||||
defaultLatitude: Number,
|
||||
defaultLongitude: Number,
|
||||
providerName: String,
|
||||
providerOptions: Object
|
||||
};
|
||||
|
||||
connect() {
|
||||
this.zoomLevel = 6;
|
||||
this.#displayMapWhenAtRegistrationDetailsStep();
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this.map.remove();
|
||||
}
|
||||
|
||||
async locateAddress() {
|
||||
const results = await this.provider.search({ query: this.#addressQuery() });
|
||||
if(results.length > 0) {
|
||||
const result = results[0];
|
||||
this.#setLatitudeLongitude(result.y, result.x);
|
||||
this.#addMarker(result.y, result.x);
|
||||
this.map.setView([result.y, result.x], this.zoomLevel);
|
||||
this.confirmAddressFieldTarget.style.display = "block";
|
||||
this.dragPinNoteTarget.style.display = "block";
|
||||
}
|
||||
}
|
||||
|
||||
#addressQuery() {
|
||||
const stateField = document.getElementById("enterprise_state");
|
||||
const state = stateField.options[stateField.selectedIndex]?.label;
|
||||
const countryField = document.getElementById("enterprise_country");
|
||||
const country = countryField.options[countryField.selectedIndex]?.label;
|
||||
const city = document.getElementById("enterprise_city")?.value;
|
||||
const zipcode = document.getElementById("enterprise_zipcode")?.value;
|
||||
const addressLine1 = document.getElementById("enterprise_address")?.value;
|
||||
const addressLine2 = document.getElementById("enterprise_address2")?.value;
|
||||
|
||||
// If someone clicks the locate address on map button without filling in their address the
|
||||
// geocoded address will not be very accurate so don't zoom in too close so it's easier for
|
||||
// people to see where the marker is.
|
||||
if(!addressLine1 && !city && !zipcode) {
|
||||
this.zoomLevel = 6;
|
||||
} else {
|
||||
this.zoomLevel = 14;
|
||||
}
|
||||
|
||||
return [addressLine1, addressLine2, city, state, zipcode, country].filter((value) => !!value).join(", ")
|
||||
}
|
||||
|
||||
#addMarker(latitude, longitude) {
|
||||
const icon = L.icon({ iconUrl: "/map_icons/map_003-producer-shop.svg" });
|
||||
this.marker = L.marker([latitude, longitude], {
|
||||
draggable: true,
|
||||
icon: icon,
|
||||
});
|
||||
|
||||
this.marker.on("dragend", (event) => {
|
||||
const position = event.target.getLatLng();
|
||||
this.#setLatitudeLongitude(position.lat, position.lng);
|
||||
});
|
||||
|
||||
this.marker.addTo(this.map);
|
||||
}
|
||||
|
||||
#displayMap() {
|
||||
this.map = L.map('open-street-map')
|
||||
L.tileLayer.provider(this.providerNameValue, this.providerOptionsValue).addTo(this.map)
|
||||
this.map.setView([this.defaultLatitudeValue, this.defaultLongitudeValue], this.zoomLevel)
|
||||
this.provider = new OpenStreetMapProvider();
|
||||
}
|
||||
|
||||
// The connect() method is called before the registration details step is visible, this
|
||||
// causes the map tiles to render incorrectly. To fix this only display the map when the
|
||||
// registration details step has been reached.
|
||||
#displayMapWhenAtRegistrationDetailsStep() {
|
||||
const observer = new IntersectionObserver(
|
||||
([intersectionObserverEntry]) => {
|
||||
if(intersectionObserverEntry.target.offsetParent !== null) {
|
||||
this.#displayMap();
|
||||
observer.disconnect()
|
||||
}
|
||||
},
|
||||
{ threshold: [0] }
|
||||
);
|
||||
observer.observe(document.getElementById("registration-details"));
|
||||
}
|
||||
|
||||
// The registration process uses Angular, set latitude and longitude data properties so the
|
||||
// Angular RegistrationCtrl controller can read and add them to the parameters it uses to create
|
||||
// new enterprises.
|
||||
#setLatitudeLongitude(latitude, longitude) {
|
||||
document.getElementById("open-street-map").dataset.latitude = latitude;
|
||||
document.getElementById("open-street-map").dataset.longitude = longitude;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,9 @@
|
||||
"hotkeys-js": "^3.13.7",
|
||||
"jquery-ui": "1.13.3",
|
||||
"js-big-decimal": "^2.0.7",
|
||||
"leaflet": "1.9.4",
|
||||
"leaflet-geosearch": "3.11.1",
|
||||
"leaflet-providers": "2.0.0",
|
||||
"moment": "^2.30.1",
|
||||
"mrujs": "^1.0.0",
|
||||
"select2": "^4.0.13",
|
||||
|
||||
27
yarn.lock
27
yarn.lock
@@ -1112,6 +1112,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.1.tgz#16308cea045f0fc777b6ff20a9f25474dd8293d2"
|
||||
integrity sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==
|
||||
|
||||
"@googlemaps/js-api-loader@^1.16.6":
|
||||
version "1.16.6"
|
||||
resolved "https://registry.yarnpkg.com/@googlemaps/js-api-loader/-/js-api-loader-1.16.6.tgz#c89970c94b55796d51746c092f0e52953994a171"
|
||||
integrity sha512-V8p5W9DbPQx74jWUmyYJOerhiB4C+MHekaO0ZRmc6lrOYrvY7+syLhzOWpp55kqSPeNb+qbC2h8i69aLIX6krQ==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.3"
|
||||
|
||||
"@hotwired/stimulus-webpack-helpers@^1.0.0":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@hotwired/stimulus-webpack-helpers/-/stimulus-webpack-helpers-1.0.1.tgz#4cd74487adeca576c9865ac2b9fe5cb20cef16dd"
|
||||
@@ -3911,7 +3918,7 @@ extglob@^2.0.4:
|
||||
snapdragon "^0.8.1"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
fast-deep-equal@^3.1.1:
|
||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
@@ -5707,6 +5714,24 @@ last-call-webpack-plugin@^3.0.0:
|
||||
lodash "^4.17.5"
|
||||
webpack-sources "^1.1.0"
|
||||
|
||||
leaflet-geosearch@3.11.1:
|
||||
version "3.11.1"
|
||||
resolved "https://registry.yarnpkg.com/leaflet-geosearch/-/leaflet-geosearch-3.11.1.tgz#e35b1e156afef388bbb42543eb56502e9a633192"
|
||||
integrity sha512-cILLFLmn8C3MtGhaafGqY7CuhUG2+bGyUgfPHgNgW6fs4EvYyiIO88nO2ZqR7Hy6Ba089haLkhODpZR+/fRrPQ==
|
||||
optionalDependencies:
|
||||
"@googlemaps/js-api-loader" "^1.16.6"
|
||||
leaflet "^1.6.0"
|
||||
|
||||
leaflet-providers@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/leaflet-providers/-/leaflet-providers-2.0.0.tgz#dfdab9ca2dccc57c79e1462bc3dd20f78910afcb"
|
||||
integrity sha512-CWwKEnHd66Qsx0m4o5q5ZOa60s00B91pMxnlr4Y22msubfs7dhbZhdMIz8bvZQkrZqi67ppI1fsZRS6vtrLcOA==
|
||||
|
||||
leaflet@1.9.4, leaflet@^1.6.0:
|
||||
version "1.9.4"
|
||||
resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.9.4.tgz#23fae724e282fa25745aff82ca4d394748db7d8d"
|
||||
integrity sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==
|
||||
|
||||
leven@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
|
||||
|
||||
Reference in New Issue
Block a user