Browse Source

Merge branch 'feature/search-map' into develop

* feature/search-map:
  DRY the rendering of "an index with map" by moving listing to partial
  Add a map to the search result page
  Extract map js generation into partial
tags/0.3.6^2
Bèr Kessels 1 month ago
parent
commit
bdb5ac9cc1

+ 34
- 0
app/assets/javascripts/application.js View File

@@ -38,6 +38,40 @@ var sourceEntry = function(feature) {
};
};

var iconFactory = function(leaflet, place_status) {
let iconUrl = '';
switch(place_status) {
case 'open':
iconUrl = '/images/marker-icon-opened.png';
break;
case 'closed':
iconUrl = '/images/marker-icon-closed.png';
break;
case 'unknown':
iconUrl = '/images/marker-icon-unknown.png';
break;
default:
iconUrl = '/images/marker-icon-unknown.png';
break;
};

return leaflet.icon({
iconUrl: iconUrl,
iconSize: [31, 41],
iconAnchor: [15, 41],
popupAnchor: [0, -28],
shadowUrl: '/images/marker-shadow.png',
shadowSize: [41, 41],
shadowAnchor: [14, 41]
});
}

var markerFactory = function(leaflet, id, y, x, icon, popup_content) {
return leaflet.marker([y, x], { icon: icon }).
on('click', highlightAsidePlace(id)).
bindPopup(popup_content);
}

var highlightAsidePlace = function(id) {
var id = 'place-' + id;
return function(e) {

+ 6
- 0
app/models/search_result.rb View File

@@ -20,6 +20,12 @@ module Hours
@paginator = paginator
end

def geometry
return Base::NULL_ISLAND if collection.empty?

collection.first.geometry
end

def collection
@collection.map do |item|
if item.nil?

+ 17
- 0
app/views/aside_places_partial.erb View File

@@ -0,0 +1,17 @@
<div class="col-3 list-group pl-3" id="map-listing">
<%- index.collection.each do |place| %>
<a href="/places/<%= place.id %>"
class="list-group-item list-group-item-action"
id="place-<%= place.id %>">
<div class="d-flex w-100 justify-content-between">
<h3 class="mb-1 small"><%= place.name %></h3>
</div>
<p class="mb-1 small"><%= place.address.street %>, <%= place.address.city %></p>
<p class="mb-1 small">
<%== erb :status_badge_partial, locals: { status: place.status } %>
<%= place.opening_hours %>
</p>
</a>
<% end %>
<%== pagy_bootstrap_nav(index.paginator) %>
</div>

+ 30
- 0
app/views/map_js_partial.erb View File

@@ -0,0 +1,30 @@
var map = L.map('map').setView([<%= index.geometry.y %>, <%= index.geometry.x %>], 16);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors'
}).addTo(map);

var centerIcon = L.icon({
iconUrl: '/images/location-icon.png',
iconSize: [40, 40],
iconAnchor: [20, 20],
popupAnchor: [-20, -40],
});

L.marker([<%==index.geometry.y %>, <%==index.geometry.x%>], {icon: centerIcon}).addTo(map);
var markers = [];

<%- index.collection.each do |place| %>
markers.push(
markerFactory(
L,
'<%== place.id %>',
<%== place.geometry.y %>,
<%== place.geometry.x %>,
iconFactory(L, '<%== place.status %>'),
'<strong><%= place.name %></strong> <%== erb(:status_badge_partial, locals: { status: place.status }).delete("\n") %>'
).addTo(map)
);
<%- end %>

var group = L.featureGroup(markers);
map.fitBounds(group.getBounds());

+ 8
- 79
app/views/region.erb View File

@@ -3,65 +3,10 @@
No places found in <%= @region.name %>
</p>
<% else %>
<%-
js = "var map = L.map('map').setView([#{@region.geometry.y}, #{@region.geometry.x}], 16);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors'
}).addTo(map);"
js += "var openedIcon = L.icon({
iconUrl: '/images/marker-icon-opened.png',
iconSize: [31, 41],
iconAnchor: [15, 41],
popupAnchor: [0, -28],
shadowUrl: '/images/marker-shadow.png',
shadowSize: [41, 41],
shadowAnchor: [14, 41]
});"
js += "var closedIcon = L.icon({
iconUrl: '/images/marker-icon-closed.png',
iconSize: [31, 41],
iconAnchor: [15, 41],
popupAnchor: [0, -28],
shadowUrl: '/images/marker-shadow.png',
shadowSize: [41, 41],
shadowAnchor: [14, 41]
});"
js += "var unknownIcon = L.icon({
iconUrl: '/images/marker-icon-unknown.png',
iconSize: [31, 41],
iconAnchor: [15, 41],
popupAnchor: [0, -28],
shadowUrl: '/images/marker-shadow.png',
shadowSize: [41, 41],
shadowAnchor: [14, 41]
});"
js += "var centerIcon = L.icon({
iconUrl: '/images/location-icon.png',
iconSize: [40, 40],
iconAnchor: [20, 20],
popupAnchor: [-20, -40],
});"

js += "L.marker([#{@region.geometry.y}, #{@region.geometry.x}], {icon: centerIcon}).addTo(map);"
js += "var markers = [];"

@region.collection.each do |place|
icon = if place.status == :open
'openedIcon'
elsif place.status == :closed
'closedIcon'
else
'unknownIcon'
end
popup_content = "<strong>#{Rack::Utils.escape_html(place.name)}</strong>"
popup_content += erb(:status_badge_partial, locals: { status: place.status }).delete("\n")
js += "markers.push(L.marker([#{place.geometry.y}, #{place.geometry.x}], {icon: #{icon}}).on('click', highlightAsidePlace('#{place.id}')).addTo(map).bindPopup('#{popup_content}'))\n;"
end

js += "var group = L.featureGroup(markers);"
js += "map.fitBounds(group.getBounds());"
set_content_for(:closing_js, js)
%>
<%- set_content_for(
:closing_js,
erb(:map_js_partial, locals: { index: @region })
) %>

<% set_content_for(:region_slug, @region.slug) %>
<% set_content_for(:region_name, @region.name) %>
@@ -69,25 +14,9 @@
<h2>Openingstijden in <%= @region.name %></h2>

<section class="row">
<div class="col-3 list-group pl-3" id="map-listing">
<%- @region.collection.each do |place| %>
<a href="/places/<%= place.id %>"
class="list-group-item list-group-item-action"
id="place-<%= place.id %>">
<div class="d-flex w-100 justify-content-between">
<h3 class="mb-1 small"><%= place.name %></h3>
</div>
<p class="mb-1 small"><%= place.address.street %>, <%= place.address.city %></p>
<p class="mb-1 small">
<%== erb :status_badge_partial, locals: { status: place.status } %>
<%= place.opening_hours %>
</p>
</a>
<% end %>
<%== pagy_bootstrap_nav(@region.paginator) %>
</div>
<div class="col">
<div id="map" class="full"></div>
</div>
<%== erb(:aside_places_partial, locals: { index: @region }) %>
<div class="col">
<div id="map" class="full"></div>
</div>
</section>
<% end %>

+ 9
- 17
app/views/search.erb View File

@@ -1,21 +1,13 @@
<h2>Zoekresultaat voor <%= @search_result.query %></h2>

<%- set_content_for(
:closing_js,
erb(:map_js_partial, locals: { index: @search_result })
) %>

<section class="row">
<div class="col-3 list-group">
<%- @search_result.collection.each do |place| %>
<a href="/places/<%= place.id %>" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h3 class="mb-1 small"><%= place.name %></h3>
</div>
<p class="mb-1 small">
<%== erb :status_badge_partial, locals: { status: place.status } %>
<%= place.opening_hours %>
</p>
</a>
<% end %>
<%== pagy_bootstrap_nav(@search_result.paginator) %>
</div>
<div class="col">
<div id="map" class="full"></div>
</div>
<%== erb(:aside_places_partial, locals: { index: @search_result }) %>
<div class="col">
<div id="map" class="full"></div>
</div>
</section>

+ 0
- 2
test/models/place_test.rb View File

@@ -54,8 +54,6 @@ describe Hours::Models::Place do
end

describe 'geometry' do
let(:nijmegen) { GeoRuby::SimpleFeatures::Point.from_xy(51.8425, 5.85278) }

it 'takes the value if set' do
subject.geometry = nijmegen
assert_equal nijmegen, subject.geometry

+ 12
- 0
test/models/search_result_test.rb View File

@@ -24,6 +24,18 @@ describe Hours::Models::SearchResult do
end
end

describe '#geometry' do
it 'without results returns NULL_ISLAND' do
subject = Hours::Models::SearchResult.new(collection: [])
assert_equal null_island, subject.geometry
end
it 'returns geometry from first result' do
place = OpenStruct.new(geometry: nijmegen)
subject = Hours::Models::SearchResult.new(collection: [place])
assert_equal nijmegen, subject.geometry
end
end

describe '#error' do
subject do
Hours::Models::SearchResult.new(collection: collection, error: 'An Error')

+ 4
- 0
test/support/location_helpers.rb View File

@@ -11,6 +11,10 @@ module LocationHelpers
GeoRuby::SimpleFeatures::Point.from_xy(0, 0)
end

def nijmegen
GeoRuby::SimpleFeatures::Point.from_xy(51.8425, 5.85278)
end

def assert_nearby(expected, actual, delta = DISTANCE_DELTA, message = nil)
[0, 1].each do |index|
vector = index.zero? ? 'lat' : 'lon'

Loading…
Cancel
Save