Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map Popups #7715

Merged
merged 14 commits into from
Mar 26, 2020
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ env:
- CI=true
- GENERATE_REPORT=true
- RAILS_ENV=test
- RAILS_SYSTEM_TESTING_SCREENSHOT=simple

before_install:
- sudo wget https://chromedriver.storage.googleapis.com/73.0.3683.68/chromedriver_linux64.zip
Expand Down Expand Up @@ -58,7 +59,7 @@ jobs:
- name: "Integration Tests"
script: bundle exec rails test test/integration
- name: "System Tests"
script: bundle exec rails test:system > /dev/null
script: bundle exec rails test:system

after_script:
- echo -e '<?xml version="1.0" encoding="UTF-8"?>' > output.xml;
Expand Down
14 changes: 11 additions & 3 deletions app/api/srch/search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -311,17 +311,23 @@ class Search < Grape::API

if results.present?
docs = results.map do |model|
doctype = model.has_power_tag('question') ? 'QUESTION' : 'NOTE'
doctype = 'WIKI' if model.type == 'page'
DocResult.new(
doc_id: model.nid,
doc_type: 'PLACES',
doc_type: doctype,
doc_url: model.path(:items),
doc_title: model.title,
doc_author: model.user.username,
doc_image_url: !model.images.empty? ? model.images.first.path : 0,
score: model.answers.length,
latitude: model.lat,
longitude: model.lon,
blurred: model.blurred?
blurred: model.blurred?,
place_name: model.has_power_tag('place') ? model.power_tag('place') : '',
created_at: model.created_at,
# time_since: distance_of_time_in_words(model.created_at, Time.current, { include_seconds: false, scope: 'datetime.time_ago_in_words' }), # works, but really slows down the search results
# comment_count: model.comments_viewable_by(current_user).length # causes an error because of current_user?
)
end
DocList.new(docs, search_request)
Expand Down Expand Up @@ -350,7 +356,9 @@ class Search < Grape::API
doc_title: model.username,
latitude: model.lat,
longitude: model.lon,
blurred: model.blurred?
blurred: model.blurred?,
created_at: model.created_at,
doc_image_url: model.profile_image ? model.profile_image : ""
)
end
DocList.new(docs, search_request)
Expand Down
3 changes: 2 additions & 1 deletion app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,5 @@
//= require jquery-validation/dist/jquery.validate.js
//= require validation.js
//= require submit_form_ajax.js
//= require urlMapHash.js
//= require urlMapHash.js
//= require timeago.js
92 changes: 58 additions & 34 deletions app/assets/javascripts/leaflet_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
return map ;
}

function PLmarker_default(){
function PLmarker_default(color = 'black'){
// valid colors: blue, gold, green, orange, yellow, violet, grey, black
L.Icon.PLmarker = L.Icon.extend({
options: {
iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-black.png',
iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-'+color+'.png',
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
iconSize: [25, 41],
iconAnchor: [12, 41],
Expand Down Expand Up @@ -51,42 +52,65 @@
}

function contentLayerParser(map, markers_hash, map_tagname) {
var NWlat = map.getBounds().getNorthWest().lat ;
var NWlng = map.getBounds().getNorthWest().lng ;
var SElat = map.getBounds().getSouthEast().lat ;
var SElng = map.getBounds().getSouthEast().lng ;
map.spin(true) ;
var NWlat = map.getBounds().getNorthWest().lat ;
var NWlng = map.getBounds().getNorthWest().lng ;
var SElat = map.getBounds().getSouthEast().lat ;
var SElng = map.getBounds().getSouthEast().lng ;
map.spin(true) ;

if(map_tagname === null || (typeof map_tagname === "undefined")) {
taglocation_url = "/api/srch/taglocations?nwlat=" + NWlat + "&selat=" + SElat + "&nwlng=" + NWlng + "&selng=" + SElng ;
if(map_tagname === null || (typeof map_tagname === "undefined")) {
taglocation_url = "/api/srch/taglocations?nwlat=" + NWlat + "&selat=" + SElat + "&nwlng=" + NWlng + "&selng=" + SElng ;

} else {
taglocation_url = "/api/srch/taglocations?nwlat=" + NWlat + "&selat=" + SElat + "&nwlng=" + NWlng + "&selng=" + SElng + "&tag=" + map_tagname ;
}
$.getJSON(taglocation_url , function (data) {
if (!!data.items) {
for (i = 0; i < data.items.length; i++) {
var url = data.items[i].doc_url;
var title = data.items[i].doc_title;
var author = data.items[i].doc_author;
var image_url = data.items[i].doc_image_url;
var default_url = PLmarker_default();
var mid = data.items[i].doc_id ;
var m = L.marker([data.items[i].latitude, data.items[i].longitude], {icon: default_url}).bindPopup("<a href=" + url + ">" + title + "</a>") ;

if(markers_hash.has(mid) === false){
} else {
taglocation_url = "/api/srch/taglocations?nwlat=" + NWlat + "&selat=" + SElat + "&nwlng=" + NWlng + "&selng=" + SElng + "&tag=" + map_tagname ;
}

if(image_url) {
m.addTo(map).bindPopup("<div><img src=" + image_url+ " height='140px' /><br>" + "<b>Title:</b> " + title + "<br><b>Author:</b> <a href=" + 'https://publiclab.org/profile/' + author + ">" + author + "</a><br>" + "<a href=" + url + ">" + "Read more..." + "</a></div>" ) ;
} else {
m.addTo(map).bindPopup("<span><b>Title:</b> " + title + "</span><br><span><b>Author:</b> <a href=" + 'https://publiclab.org/profile/' + author + ">" + author + "</a></span><br>" + "<a href=" + url + ">" + "<br>Read more..." + "</a>" ) ;
}
markers_hash.set(mid , m) ;
}
$.getJSON(taglocation_url , function (data) {
if (!!data.items) {
for (i = 0; i < data.items.length; i++) {
var nodetype = data.items[i].doc_type;
nodetype = nodetype.charAt(0).toUpperCase() + nodetype.slice(1).toLowerCase();

var place_name = data.items[i].place_name;
var url = data.items[i].doc_url;
var title = data.items[i].doc_title;
var author = data.items[i].doc_author;
var image_url = data.items[i].doc_image_url;
var map_marker = PLmarker_default('blue');
var mid = data.items[i].doc_id;
var created_at = data.items[i].created_at;
var time_since = TimeAgo().inWords(new Date(data.items[i].created_at));
// var comment_count = data.items[i].comment_count;

var m = L.marker([data.items[i].latitude, data.items[i].longitude], {icon: map_marker});

if(markers_hash.has(mid) === false){
var popup_content = "";
if (image_url) popup_content += "<img src='" + image_url + "' class='popup-thumb' />";
popup_content += "<h5><a href='" + url + "'>" + limit_words(title, 10) + "</a></h5>";
popup_content += "<div class='popup-two-column'>";
popup_content += "<div class='popup-stretch-column'>" + nodetype + " by <a href='https://publiclab.org/profile/" + author + "'>@" + author + "</a> " + time_since + "</div><br>";
if (nodetype.toLowerCase() === "wiki") popup_content += "<div class='map-slug popup-shrink-column'><a href='/map/" + url.split('/').pop() + "'>#</a></div>";
popup_content += "</div>";
// if (place_name) popup_content += "<span><b>Place: </b>" + place_name + "</span><br>";

var popup = L.popup({
maxWidth: 300,
autoPan: false,
className: 'map-popup'
}).setContent(popup_content);
m.addTo(map).bindPopup(popup_content);

markers_hash.set(mid , m) ;
}
}
map.spin(false) ;
});
}
}
map.spin(false) ;
});

function limit_words(str, num_words) {
return str.split(" ").splice(0, num_words).join(" ");
}
}

function setupLEL(map, markers_hash = null, params = {}) {
Expand Down
63 changes: 63 additions & 0 deletions app/assets/javascripts/timeago.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Function by caiotarifa: https://gist.github.com/caiotarifa/30ae974f2293c761f3139dd194abd9e5
//
// using this function instead of distance_of_time_in_words in Ruby for the map popups calculation in leaflet_helper.js

var TimeAgo = (function() {
var self = {};

// Public Methods
self.locales = {
prefix: '',
sufix: 'ago',

seconds: '1 minute',
minute: '1 minute',
minutes: '%d minutes',
hour: '1 hour',
hours: '%d hours',
day: '1 day',
days: '%d days',
month: '1 month',
months: '%d months',
year: '1 year',
years: '%d years'
};

self.inWords = function(timeAgo) {

var seconds = Math.floor((new Date() - new Date(timeAgo)) / 1000),
separator = this.locales.separator || ' ',
words = this.locales.prefix + separator,
interval = 0,
intervals = {
year: seconds / 31536000,
month: seconds / 2592000,
day: seconds / 86400,
hour: seconds / 3600,
minute: seconds / 60
};

var distance = this.locales.seconds;

for (var key in intervals) {
if (intervals.hasOwnProperty(key)) {
interval = Math.floor(intervals[key]);

if (interval > 1) {
distance = this.locales[key + 's'];
break;
} else if (interval === 1) {
distance = this.locales[key];
break;
}
}
}

distance = distance.replace(/%d/i, interval);
words += distance + separator + this.locales.sufix;

return words.trim();
};

return self;
}());
25 changes: 22 additions & 3 deletions app/assets/stylesheets/map.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,26 @@
.leaflet-top{
z-index:800 !important;
}
.leaflet-popup-content {
width: 800px !important;
.leaflet-popup .leaflet-popup-content {
width: 300px;
max-width: 300px;
margin: 15px;
}

.leaflet-popup .leaflet-popup-content img.popup-thumb {
width: 100%;
margin-bottom: 15px;
}
.leaflet-popup .leaflet-popup-content h5 {
margin-bottom: 4px;
}
.leaflet-popup .popup-two-column {
display: flex;
width: 100%;
justify-content: space-between;
}
.leaflet-popup .popup-stretch-column {
flex: 1 1 100%;
}
.leaflet-popup .popup-shrink-column {
flex: 0 1 auto;
}
10 changes: 9 additions & 1 deletion app/models/doc_result.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# A DocResult is an individual return item for a document (web page) search
class DocResult
attr_accessor :doc_id, :doc_type, :doc_url, :doc_title, :doc_score, :latitude, :longitude, :blurred, :category, :doc_author, :doc_image_url
attr_accessor :doc_id, :doc_type, :doc_url, :doc_title, :doc_score, :latitude, :longitude, :blurred, :category, :doc_author, :doc_image_url, :place_name, :created_at, :comment_count, :time_since, :user_photo_path

def initialize(args = {})
@doc_id = args[:doc_id]
Expand All @@ -14,6 +14,10 @@ def initialize(args = {})
@longitude = args[:longitude]
@blurred = args[:blurred]
@category = args[:doc_type]
@place_name = args[:place_name]
@created_at = args[:created_at]
@time_since = args[:time_since]
@comment_count = args[:comment_count]
end

# This subclass is used to auto-generate the RESTful data structure. It is generally not useful for internal Ruby usage
Expand All @@ -26,5 +30,9 @@ class Entity < Grape::Entity
expose :doc_score, documentation: { type: 'Float', desc: "If calculated, the relevance of the document result to the search request; i.e. the 'matching score'" }
expose :latitude, documentation: { type: 'String', desc: "Returns the latitude associated with the node." }
expose :longitude, documentation: { type: 'String', desc: "Returns the longitude associated with the node." }
expose :place_name, documentation: { type: 'String', desc: "Returns the place name of the location associated with the node." }
expose :created_at, documentation: { type: 'String', desc: "Returns the date the node was created." }
expose :time_since, documentation: { type: 'String', desc: "Returns a description of the amount of time that has passed since the node was created." }
expose :comment_count, documentation: { type: 'String', desc: "Returns the number of comments the user can view belonging to the node." }
end
end
5 changes: 1 addition & 4 deletions app/views/map/_inlineLeaflet.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
#postOnMap<%= unique_id %> {
margin-top: 5px;
}
.leaflet-popup-content {
width: auto !important;
}
a.grid-embed {
float:right;
padding:8px;
Expand All @@ -17,7 +14,7 @@
}
</style>

<div class="leaflet-map inline-fullwidth-content" id="map<%= unique_id %>"></div>
<div class="leaflet-map inline-map inline-fullwidth-content" id="map<%= unique_id %>"></div>

<a id="iframeID<%= unique_id %>" class="grid-embed" rel="tooltip" title="Embed this map on another site."><i class="fa fa-code" style="color:#aaa;"></i></a>

Expand Down
2 changes: 1 addition & 1 deletion app/views/map/_leaflet.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<style>
#map<%= unique_id %> { width:100%; height:300px; margin: 0; position: relative;}
</style>
<div class="leaflet-map" id="map<%= unique_id %>"></div>
<div class="leaflet-map sidebar-top-map" id="map<%= unique_id %>"></div>
<% if defined? people %><p><i><small>Share your own location on <a href='/profile'>your profile</a>.</small></i></p><% end %>
<% end %>

Expand Down
2 changes: 1 addition & 1 deletion app/views/map/_peopleLeaflet.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</style>

<div>
<div class="leaflet-map" id="map<%= unique_id %>"></div>
<div class="leaflet-map inline-map" id="map<%= unique_id %>"></div>
</div>

<p><i><small>
Expand Down
5 changes: 1 addition & 4 deletions app/views/map/_plainInlineLeaflet.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@
#postOnMap<%= unique_id %> {
margin-top: 5px;
}
.leaflet-popup-content {
width: auto !important;
}
</style>
<div class="inline-fullwidth-content">
<div class="leaflet-map" id="map<%= unique_id %>"></div>
<div class="leaflet-map inline-map" id="map<%= unique_id %>"></div>
</div>


Expand Down
18 changes: 18 additions & 0 deletions test/fixtures/node_tags.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,21 @@ test4_zoom:
uid: 1
nid: 7
date: <%= DateTime.now.to_i %>

organizers-awesome:
tid: 2
uid: 2
nid: 5
date: <%= DateTime.now.to_i %>

organizers-everything:
tid: 4
uid: 2
nid: 5
date: <%= DateTime.now.to_i %>

organizers-chapter:
tid: 5
uid: 2
nid: 5
date: <%= DateTime.now.to_i %>
2 changes: 1 addition & 1 deletion test/functional/tag_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ def setup

assert_response :success
assert_select 'table' # ensure a table is shown
assert_equal 3, css_select('tr').length # ensure it has 3 rows
assert_equal 4, css_select('tr').length # ensure it has 4 rows
end

test 'rss with tagname and authorname' do
Expand Down
3 changes: 0 additions & 3 deletions test/system/map_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ class MapTest < ApplicationSystemTestCase
page.execute_script("map.setView([13, 60], 15)")
url_hash = page.evaluate_script("window.location.hash")

# Wait for any potential asynchronous operations to complete
wait_for_ajax

# check that the url hash is correct
assert_equal("#15/13/60", url_hash)
end
Expand Down
Loading