Skip to content

Commit

Permalink
Several improvements in solr-based maps
Browse files Browse the repository at this point in the history
* Add support for solr-based queries in map
* Add navigation links from search page to map page and vice versa
 * Improvements in map embeds code
* Remove old unneeded geotags box code
* Use solr backend in tag/user/pack map pages
  • Loading branch information
ffont committed Feb 8, 2024
1 parent 30a1dc8 commit ef508e1
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 116 deletions.
9 changes: 2 additions & 7 deletions accounts/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,14 +287,9 @@ def test_sound_search_response(self):
resp = self.client.get(reverse('sounds-search'))
self.assertEqual(resp.status_code, 200)

def test_geotags_box_response(self):
# 200 response on geotag box page access
resp = self.client.get(reverse('geotags-box'))
self.assertEqual(resp.status_code, 200)

def test_geotags_box_iframe_response(self):
def test_geotags_embed_response(self):
# 200 response on geotag box iframe
resp = self.client.get(reverse('embed-geotags-box-iframe'))
resp = self.client.get(reverse('embed-geotags'))
self.assertEqual(resp.status_code, 200)

def test_accounts_manage_pages(self):
Expand Down
2 changes: 1 addition & 1 deletion freesound/static/bw-frontend/src/components/mapsMapbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ function makeSoundsMap(geotags_url, map_element_id, on_built_callback, on_bounds
if (nSounds > 1){
// The padding and offset "manual" adjustments of bounds below are to make the boudns more similar to
// those created in the mapbox static maps
map.fitBounds(bounds, {duration:0, offset:[-10, 0], padding: {top:60, right:60, left:0, bottom:50}});
map.fitBounds(bounds, {duration:0, offset:[0, 0], padding: {top:60, right:60, left:60, bottom:60}});
} else {
map.setZoom(3);
if (nSounds > 0){
Expand Down
45 changes: 20 additions & 25 deletions freesound/static/bw-frontend/src/pages/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ const tagFilterInput = document.getElementById("tagFilter");
let currentLat;
let currentLon;
let currentZoom;
let currentBoxBlLa;
let currentBoxBlLon;
let currentBoxTrLat;
let currentBoxTrLon;

const toggleEmbedControls = () => {
if (embedControls.classList.contains('display-none')){
Expand All @@ -42,22 +38,21 @@ const updateQueryStringParameter = (uri, key, value) => {
}
}

const updateEmbedCode = (mapElementId, lat, lon, zoom, boxBlLat, boxBlLon, boxTrLat, boxTrLon) => {
const updateEmbedCode = (mapElementId, lat, lon, zoom) => {
if (embedCodeElement === null){ return; }

const mapCanvas = document.getElementById(mapElementId);
let mapCanvas;
if (mapElementId === undefined){
mapCanvas = document.getElementsByClassName('main-map')[0];
} else {
mapCanvas = document.getElementById(mapElementId);
}

// Store lat, lon and zoom globally so we can use them later to call updateEmbedCode without accessing map
currentLat = lat;
currentLon = lon;
currentZoom = zoom;
currentBoxBlLa = boxBlLat;
currentBoxBlLon = boxBlLon;
currentBoxTrLat = boxTrLat;
currentBoxTrLon = boxTrLon;

// Generate embed code
const box = "#box=" + boxBlLat + "," + boxBlLon+"," + boxTrLat+"," + boxTrLon;
const width = parseInt(embedWidthInputElement.value, 10);
const height = parseInt(embedHeightInputElement.value, 10);
let cluster = 'on';
Expand All @@ -66,16 +61,19 @@ const updateEmbedCode = (mapElementId, lat, lon, zoom, boxBlLat, boxBlLon, boxTr
}
let embedCode = "<iframe frameborder=\"0\" scrolling=\"no\" src=\"" + mapCanvas.dataset.geotagsEmbedBaseUrl
+ "?c_lat=" + lat + "&c_lon=" + lon + "&z=" + zoom + "&c=" + cluster + "&w=" + width + "&h=" + height;
if (mapCanvas.dataset.mapUsername !== "None"){
if (mapCanvas.dataset.mapUsername !== ""){
embedCode += "&username=" + mapCanvas.dataset.mapUsername;
}
if (mapCanvas.dataset.mapTag !== "None"){
if (mapCanvas.dataset.mapTag !== ""){
embedCode += "&tag=" + mapCanvas.dataset.mapTag;
}
if (mapCanvas.dataset.mapPackId !== "None"){
if (mapCanvas.dataset.mapPackId !== ""){
embedCode += "&pack=" + mapCanvas.dataset.mapPackId;
}
embedCode += box + "\" width=\"" + width + "\" height=\"" + height + "\"></iframe>";
if (mapCanvas.dataset.mapQp !== ""){
embedCode += "&qp=" + mapCanvas.dataset.mapQp;
}
embedCode += "\" width=\"" + width + "\" height=\"" + height + "\"></iframe>";
embedCodeElement.innerText = embedCode;

// Update page URL so it can directly be used to share the map
Expand All @@ -87,7 +85,7 @@ const updateEmbedCode = (mapElementId, lat, lon, zoom, boxBlLat, boxBlLon, boxTr
}

const changeEmbedWidthHeightCluster = () => {
updateEmbedCode(undefined, currentLat, currentLon, currentZoom, currentBoxBlLa, currentBoxBlLon, currentBoxTrLat, currentBoxTrLon);
updateEmbedCode(undefined, currentLat, currentLon, currentZoom);
}

const initMap = (mapCanvas) => {
Expand All @@ -107,7 +105,7 @@ const initMap = (mapCanvas) => {
[embedWidthInputElement, embedHeightInputElement, embedClusterCheckElement].forEach(element => {
if (element !== null){
element.addEventListener('change', () => {
changeEmbedWidthHeightCluster();
changeEmbedWidthHeightCluster();
});
}
});
Expand Down Expand Up @@ -140,13 +138,6 @@ const initMap = (mapCanvas) => {
zoom = mapCanvas.dataset.mapZoom;
}
let url = mapCanvas.dataset.geotagsUrl;
const urlBox = mapCanvas.dataset.geotagsUrlBox;
const box = document.location.hash.slice(5, document.location.hash.length);
if (box !== ''){
// If box is given, get the geotags only from that box
url = `${urlBox}?box=${box}`;
}

const showSearch = (mapCanvas.dataset.mapShowSearch !== undefined && mapCanvas.dataset.mapShowSearch === 'true');
const showStyleSelector = true;
const clusterGeotags = true;
Expand All @@ -156,7 +147,11 @@ const initMap = (mapCanvas) => {
if (loadingIndicator !== null){
loadingIndicator.innerText = `${numLoadedSounds} sound${ numLoadedSounds === 1 ? '': 's'}`;
}
embedWidthInputElement.value = mapCanvas.offsetWidth;
embedHeightInputElement.value = mapCanvas.offsetHeight;
}, updateEmbedCode, centerLat, centerLon, zoom, showSearch, showStyleSelector, clusterGeotags, showMapEvenIfNoGeotags);


}

export { initMap };
4 changes: 2 additions & 2 deletions freesound/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
path('charts/', accounts.views.charts, name="charts"),

path('embed/sound/iframe/<int:sound_id>/simple/<player_size>/', sounds.views.embed_iframe, name="embed-simple-sound-iframe"),
path('embed/geotags_box/iframe/', geotags.views.embed_iframe, name="embed-geotags-box-iframe"),
path('embed/geotags_box/iframe/', geotags.views.embed_iframe, name="embed-geotags"),
path('oembed/', sounds.views.oembed, name="oembed-sound"),

path('after-download-modal/', sounds.views.after_download_modal, name="after-download-modal"),
Expand All @@ -93,7 +93,7 @@
path('browse/packs/', sounds.views.packs, name="packs"),
path('browse/random/', sounds.views.random, name="sounds-random"),
re_path(r'^browse/geotags/(?P<tag>[\w-]+)?/?$', geotags.views.geotags, name="geotags"),
path('browse/geotags_box/', geotags.views.geotags_box, name="geotags-box"),
path('browse/query/', geotags.views.for_query, name="geotags-query"),

path('contact/', support.views.contact, name="contact"),

Expand Down
14 changes: 7 additions & 7 deletions geotags/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,8 @@ def test_browse_geotags(self):
check_values = {'tag': 'soundscape', 'username': None}
self.check_context(resp.context, check_values)

def test_browse_geotags_box(self):
resp = self.client.get(reverse('geotags-box'))
check_values = {'center_lat': None, 'center_lon': None, 'zoom': None, 'username': None}
self.check_context(resp.context, check_values)

def test_geotags_box_iframe(self):
resp = self.client.get(reverse('embed-geotags-box-iframe'))
def test_geotags_embed(self):
resp = self.client.get(reverse('embed-geotags'))
check_values = {'m_width': 942, 'm_height': 600, 'cluster': True, 'center_lat': None, 'center_lon': None,
'zoom': None, 'username': None}
self.check_context(resp.context, check_values)
Expand Down Expand Up @@ -96,3 +91,8 @@ def test_browse_geotags_case_insensitive(self):
# Response contains 3 int32 objects per sound: id, lat and lng. Total size = 3 * 4 bytes = 12 bytes
n_sounds = len(resp.content) // 12
self.assertEqual(n_sounds, 2)

def test_browse_geotags_for_query(self):
resp = self.client.get(reverse('geotags-query') + f'?q=barcelona')
check_values = {'query_description': 'barcelona'}
self.check_context(resp.context, check_values)
1 change: 0 additions & 1 deletion geotags/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,5 @@
path('sounds_barray/sound/<int:sound_id>/', geotags.geotag_for_sound_barray, name="geotags-for-sound-barray"),
path('sounds_barray/query/', geotags.geotags_for_query_barray, name="geotags-for-query-barray"),
re_path(r'^sounds_barray/(?P<tag>[\w-]+)?/?$', geotags.geotags_barray, name="geotags-barray"),
path('geotags_box_barray/', geotags.geotags_box_barray, name="geotags-box-barray"),
path('infowindow/<int:sound_id>/', geotags.infowindow, name="geotags-infowindow"),
]
82 changes: 47 additions & 35 deletions geotags/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from django.urls import reverse
from django.views.decorators.cache import cache_page
from django.views.decorators.clickjacking import xframe_options_exempt
from accounts.models import Profile

from search.views import search_prepare_parameters
from sounds.models import Sound, Pack
Expand All @@ -51,7 +52,7 @@ def update_query_params_for_map_query(query_params, preserve_facets=False):
# Force is_geotagged filter to be present
if query_params['query_filter']:
if 'is_geotagged' not in query_params['query_filter']:
query_params['query_filter'] = query_params['query_filter'] + ' +is_geotagged:1'
query_params['query_filter'] = query_params['query_filter'] + ' is_geotagged:1'
else:
query_params['query_filter'] = 'is_geotagged:1'
# Force one single page with "all" results, and don't group by pack
Expand Down Expand Up @@ -113,37 +114,18 @@ def geotags_barray(request, tag=None):
return HttpResponse(generated_bytearray, content_type='application/octet-stream')


def geotags_box_barray(request):
box = request.GET.get("box", "-180,-90,180,90")
is_embed = request.GET.get("embed", "0") == "1"
try:
min_lat, min_lon, max_lat, max_lon = box.split(",")
qs = Sound.objects.select_related("geotag").exclude(geotag=None).filter(moderation_state="OK", processing_state="OK")
sounds = []
if min_lat <= max_lat and min_lon <= max_lon:
sounds = qs.filter(geotag__lat__range=(min_lat, max_lat)).filter(geotag__lon__range=(min_lon, max_lon))
elif min_lat > max_lat and min_lon <= max_lon:
sounds = qs.exclude(geotag__lat__range=(max_lat, min_lat)).filter(geotag__lon__range=(min_lon, max_lon))
elif min_lat <= max_lat and min_lon > max_lon:
sounds = qs.filter(geotag__lat__range=(min_lat, max_lat)).exclude(geotag__lon__range=(max_lon, min_lon))
elif min_lat > max_lat and min_lon > max_lon:
sounds = qs.exclude(geotag__lat__range=(max_lat, min_lat)).exclude(geotag__lon__range=(max_lon, min_lon))

generated_bytearray, num_geotags = generate_bytearray(sounds)
if num_geotags > 0:
log_map_load('box-embed' if is_embed else 'box', num_geotags, request)
return HttpResponse(generated_bytearray, content_type='application/octet-stream')
except ValueError:
raise Http404


@redirect_if_old_username_or_404
@raise_404_if_user_is_deleted
@cache_page(60 * 15)
def geotags_for_user_barray(request, username):
profile = get_object_or_404(Profile, user__username=username)
is_embed = request.GET.get("embed", "0") == "1"
sounds = Sound.public.select_related('geotag').filter(user__username__iexact=username).exclude(geotag=None)
generated_bytearray, num_geotags = generate_bytearray(sounds)
results, _ = perform_search_engine_query({
'query_filter': f'username:"{username}" is_geotagged:1', # No need to urlencode here as it will happpen somwhere before sending query to solr
'field_list': ['id', 'score', 'geotag'],
'num_sounds': profile.num_sounds,
})
generated_bytearray, num_geotags = generate_bytearray(results.docs)
if num_geotags > 0:
log_map_load('user-embed' if is_embed else 'user', num_geotags, request)
return HttpResponse(generated_bytearray, content_type='application/octet-stream')
Expand All @@ -160,8 +142,13 @@ def geotags_for_user_latest_barray(request, username):


def geotags_for_pack_barray(request, pack_id):
sounds = Sound.public.select_related('geotag').filter(pack__id=pack_id).exclude(geotag=None)
generated_bytearray, num_geotags = generate_bytearray(sounds)
pack = get_object_or_404(Pack, id=pack_id)
results, _ = perform_search_engine_query({
'query_filter': f'grouping_pack:"{pack.id}_{pack.name}" is_geotagged:1', # No need to urlencode here as it will happpen somwhere before sending query to solr
'field_list': ['id', 'score', 'geotag'],
'num_sounds': pack.num_sounds,
})
generated_bytearray, num_geotags = generate_bytearray(results.docs)
if num_geotags > 0:
log_map_load('pack', num_geotags, request)
return HttpResponse(generated_bytearray, content_type='application/octet-stream')
Expand Down Expand Up @@ -208,6 +195,7 @@ def _get_geotags_query_params(request):
def geotags(request, tag=None):
tvars = _get_geotags_query_params(request)
if tag is None:
query_search_page_url = ''
url = reverse('geotags-barray')
# If "all geotags map" and no lat/lon/zoom is indicated, center map so whole world is visible
if tvars['center_lat'] is None:
Expand All @@ -218,12 +206,14 @@ def geotags(request, tag=None):
tvars['zoom'] = 2
else:
url = reverse('geotags-barray', args=[tag])
query_search_page_url = reverse('sounds-search') + f'?f=tag:{tag}&mm=1'

tvars.update({ # Overwrite tag and username query params (if present)
'tag': tag,
'username': None,
'pack': None,
'url': url,
'query_search_page_url': query_search_page_url
})
return render(request, 'geotags/geotags.html', tvars)

Expand All @@ -238,6 +228,7 @@ def for_user(request, username):
'pack': None,
'sound': None,
'url': reverse('geotags-for-user-barray', args=[username]),
'query_search_page_url': reverse('sounds-search') + f'?f=username:{username}&mm=1'
})
return render(request, 'geotags/geotags.html', tvars)

Expand Down Expand Up @@ -278,6 +269,7 @@ def for_pack(request, username, pack_id):
'pack': pack,
'sound': None,
'url': reverse('geotags-for-pack-barray', args=[pack.id]),
'query_search_page_url': reverse('sounds-search') + f'?f=grouping_pack:"{pack.id}_{urllib.parse.quote(pack.name)}"&mm=1',
'modal_version': request.GET.get('ajax'),
})
if request.GET.get('ajax'):
Expand All @@ -288,12 +280,32 @@ def for_pack(request, username, pack_id):
return render(request, 'geotags/geotags.html', tvars)


def geotags_box(request):
# This view works the same as "geotags" but it takes the username/tag parameter from query parameters and
# onyl gets the geotags for a specific bounding box specified via hash parameters.
# Currently we are only keeping this as legacy because it is not used anymore but there might still be
# links pointing to it.
def for_query(request):
tvars = _get_geotags_query_params(request)
request_parameters_string = request.get_full_path().split('?')[-1]
q = request.GET.get('q', None)
f = request.GET.get('f', None)
query_description = ''
if q is None and f is None:
query_description = 'Empty query'
elif q is not None and f is not None:
query_description = f'{q} (some filters applied)'
else:
if q is not None:
query_description = q
if f is not None:
query_description = f'Empty query with some filtes applied'
tvars.update({
'tag': None,
'username': None,
'pack': None,
'sound': None,
'query_params': request_parameters_string,
'query_params_encoded': urllib.parse.quote(request_parameters_string),
'query_search_page_url': reverse('sounds-search') + f'?{request_parameters_string}',
'query_description': query_description,
'url': reverse('geotags-for-query-barray') + f'?{request_parameters_string}',
})
return render(request, 'geotags/geotags.html', tvars)


Expand All @@ -306,7 +318,7 @@ def embed_iframe(request):
'cluster': request.GET.get('c', 'on') != 'off'
})
tvars.update({'mapbox_access_token': settings.MAPBOX_ACCESS_TOKEN})
return render(request, 'embeds/geotags_box_iframe.html', tvars)
return render(request, 'embeds/geotags_embed.html', tvars)


def infowindow(request, sound_id):
Expand Down
Loading

0 comments on commit ef508e1

Please sign in to comment.