Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions app/assets/javascripts/members.js.erb
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,44 @@ if (document.getElementById("membermap") !== null) {
});

}

$(document).on('click', '#find-me', function(e) {
e.preventDefault();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
$('#member_latitude').val(position.coords.latitude);
$('#member_longitude').val(position.coords.longitude);
updateMap(position.coords.latitude, position.coords.longitude);
});
} else {
alert("Geolocation is not supported by this browser.");
}
});

if (document.getElementById("map") !== null) {
var map = L.map('map').setView([0, 0], 2);
var marker;

L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
maxZoom: 18
}).addTo(map);

map.on('click', function(e) {
updateMarker(e.latlng);
$('#member_latitude').val(e.latlng.lat);
$('#member_longitude').val(e.latlng.lng);
});

function updateMarker(latlng) {
if (marker) {
map.removeLayer(marker);
}
marker = L.marker(latlng).addTo(map);
}

function updateMap(lat, lng) {
map.setView([lat, lng], 13);
updateMarker(L.latLng(lat, lng));
}
}
34 changes: 32 additions & 2 deletions app/controllers/members_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

class MembersController < ApplicationController
load_and_authorize_resource except: %i(finish_signup unsubscribe view_follows view_followers show)
load_and_authorize_resource except: %i(finish_signup unsubscribe view_follows view_followers show set_location update_location)
skip_authorize_resource only: %i(nearby unsubscribe finish_signup)
respond_to :html, :json, :rss

Expand Down Expand Up @@ -86,6 +86,36 @@ def finish_signup
end
end

def set_location
@member = Member.find_by_slug!(params[:id])
authorize! :update, @member
end

def update_location
@member = Member.find_by_slug!(params[:id])
authorize! :update, @member

if params[:member][:latitude].present? && params[:member][:longitude].present?
lat = params[:member][:latitude].to_f.round(2)
lng = params[:member][:longitude].to_f.round(2)
params[:member][:latitude] = lat
params[:member][:longitude] = lng

results = Geocoder.search([lat, lng])
if results.first
params[:member][:location] = results.first.city || results.first.town || results.first.village || results.first.hamlet
else
params[:member][:location] = "Location near #{lat}, #{lng}"
end
end

if @member.update(member_params)
redirect_to member_path(@member), notice: 'Location updated.'
else
render :set_location
end
end

private

EMAIL_TYPE_STRING = {
Expand All @@ -94,7 +124,7 @@ def finish_signup
}.freeze

def member_params
params.require(:member).permit(:login_name, :tos_agreement, :email, :newsletter)
params.require(:member).permit(:login_name, :tos_agreement, :email, :newsletter, :location, :latitude, :longitude)
end

def member_json_fields
Expand Down
23 changes: 23 additions & 0 deletions app/views/members/set_location.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
- content_for :title, "Set your location"

%h1 Set your location

= form_for @member, url: update_location_member_path(@member), method: :put do |f|
.form-group
= f.label :location
= f.text_field :location, class: 'form-control'

.form-group
= f.label :latitude
= f.text_field :latitude, class: 'form-control', readonly: true

.form-group
= f.label :longitude
= f.text_field :longitude, class: 'form-control', readonly: true

#map.set-location-map

.form-group
%button#find-me.btn.btn-default Find my location

= f.submit 'Update location', class: 'btn btn-primary'
3 changes: 3 additions & 0 deletions app/views/members/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@
= link_to edit_member_registration_path, class: 'btn btn-block' do
= member_icon
= t('members.edit_profile')
= link_to set_location_member_path(@member), class: 'btn btn-block' do
= icon('fas', 'map-marker')
Set location

- if can?(:create, Notification) && current_member != @member
= link_to new_message_path(recipient_id: @member.id), class: 'btn btn-block' do
Expand Down
4 changes: 4 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@
resources :timeline

resources :members, param: :slug do
member do
get :set_location
put :update_location
end
resources :gardens
resources :seeds
resources :plantings
Expand Down
83 changes: 83 additions & 0 deletions spec/features/members/set_location_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
require 'rails_helper'

RSpec.feature 'Set location', type: :feature do
let(:member) { FactoryBot.create(:member) }

before do
login_as(member, scope: :member)
end

scenario 'member sets their location by clicking on the map', js: true do
visit set_location_member_path(member)

# Test clicking on the map
page.execute_script("map.fire('click', { latlng: L.latLng(40.7128, -74.0060) })")
expect(find('#member_latitude').value).to eq('40.7128')
expect(find('#member_longitude').value).to eq('-74.006')

# Mock geocoding
geocoder_result = instance_double('Geocoder::Result::Nominatim',
city: 'New York',
town: nil,
village: nil,
hamlet: nil)
allow(Geocoder).to receive(:search).with([40.71, -74.01]).and_return([geocoder_result])

click_button 'Update location'

expect(page).to have_content('Location updated.')
member.reload
expect(member.location).to eq('New York')
expect(member.latitude).to eq(40.71)
expect(member.longitude).to eq(-74.01)
end

scenario 'member uses "Find my location"', js: true do
visit set_location_member_path(member)

# Mock browser's geolocation
page.execute_script("
navigator.geolocation.getCurrentPosition = function(success) {
var position = { coords: { latitude: 34.0522, longitude: -118.2437 } };
success(position);
}
")

click_button 'Find my location'

expect(find('#member_latitude').value).to eq('34.0522')
expect(find('#member_longitude').value).to eq('-118.2437')

# Mock geocoding
geocoder_result = instance_double('Geocoder::Result::Nominatim',
city: 'Los Angeles',
town: nil,
village: nil,
hamlet: nil)
allow(Geocoder).to receive(:search).with([34.05, -118.24]).and_return([geocoder_result])

click_button 'Update location'

expect(page).to have_content('Location updated.')
member.reload
expect(member.location).to eq('Los Angeles')
expect(member.latitude).to eq(34.05)
expect(member.longitude).to eq(-118.24)
end

scenario 'geocoding fails', js: true do
visit set_location_member_path(member)

page.execute_script("map.fire('click', { latlng: L.latLng(1.2345, 6.7890) })")

allow(Geocoder).to receive(:search).with([1.23, 6.79]).and_return([])

click_button 'Update location'

expect(page).to have_content('Location updated.')
member.reload
expect(member.location).to eq('Location near 1.23, 6.79')
expect(member.latitude).to eq(1.23)
expect(member.longitude).to eq(6.79)
end
end
Loading