diff --git a/src/agenda_culturel/serializers/__init__.py b/src/agenda_culturel/serializers/__init__.py
new file mode 100644
index 0000000..40bb118
--- /dev/null
+++ b/src/agenda_culturel/serializers/__init__.py
@@ -0,0 +1 @@
+from .place_serializer import PlaceSerializer
diff --git a/src/agenda_culturel/serializers/place_serializer.py b/src/agenda_culturel/serializers/place_serializer.py
new file mode 100644
index 0000000..c9dfc47
--- /dev/null
+++ b/src/agenda_culturel/serializers/place_serializer.py
@@ -0,0 +1,30 @@
+from rest_framework import serializers
+from ..models import Place
+
+
+class PlaceSerializer(serializers.ModelSerializer):
+ lat = serializers.SerializerMethodField()
+ lng = serializers.SerializerMethodField()
+ url = serializers.SerializerMethodField()
+
+ class Meta:
+ model = Place
+ fields = [
+ "name",
+ "address",
+ "postcode",
+ "city",
+ "description",
+ "lat",
+ "lng",
+ "url",
+ ]
+
+ def get_lat(self, obj):
+ return obj.location[1] if obj.location else None
+
+ def get_lng(self, obj):
+ return obj.location[0] if obj.location else None
+
+ def get_url(self, obj):
+ return obj.get_absolute_url()
diff --git a/src/agenda_culturel/settings/base.py b/src/agenda_culturel/settings/base.py
index d2149f2..bf3b341 100644
--- a/src/agenda_culturel/settings/base.py
+++ b/src/agenda_culturel/settings/base.py
@@ -72,6 +72,7 @@ INSTALLED_APPS = [
"django_cleanup.apps.CleanupConfig",
"django_unused_media",
"solo.apps.SoloAppConfig",
+ "rest_framework",
]
SOLO_CACHE_TIMEOUT = 60 * 15 # 15 minutes
diff --git a/src/agenda_culturel/static/location_field/js/form.js b/src/agenda_culturel/static/location_field/js/form.js
index 528c0c4..561c623 100644
--- a/src/agenda_culturel/static/location_field/js/form.js
+++ b/src/agenda_culturel/static/location_field/js/form.js
@@ -375,6 +375,10 @@ var SequentialLoader = function() {
_getMap: function(mapOptions) {
var map = new L.Map(this.options.id, mapOptions), layer;
+ if (window.loadTiles !== undefined) {
+ window.loadTiles(map);
+ }
+
if (this.options.provider == 'google') {
layer = new L.gridLayer.googleMutant({
type: this.options.providerOptions.google.mapType.toLowerCase(),
@@ -397,25 +401,6 @@ var SequentialLoader = function() {
map.addLayer(layer);
- if ((window.other_markers !== null) && (window.other_markers.length > 0)) {
- var layerGroup = L.layerGroup().addTo(map);
- window.other_markers.forEach(x => layerGroup.addLayer(x));
- map.removeLayer(layerGroup);
- map.on('zoomend', function () {
- var currentZoom = map.getZoom();
-
- if (currentZoom > 12) {
- if (!map.hasLayer(layerGroup)) {
- map.addLayer(layerGroup);
- }
- } else {
- if (map.hasLayer(layerGroup)) {
- map.removeLayer(layerGroup);
- }
- }
- });
- }
-
return map;
},
@@ -434,7 +419,8 @@ var SequentialLoader = function() {
var self = this,
markerOptions = {
draggable: true,
- icon: window.pinIcon
+ icon: window.pinIcon,
+ zIndexOffset: 1000,
};
var marker = L.marker(center, markerOptions).addTo(map);
diff --git a/src/agenda_culturel/templates/agenda_culturel/place_form.html b/src/agenda_culturel/templates/agenda_culturel/place_form.html
index 50390d1..091123b 100644
--- a/src/agenda_culturel/templates/agenda_culturel/place_form.html
+++ b/src/agenda_culturel/templates/agenda_culturel/place_form.html
@@ -37,18 +37,51 @@
shadowSize: [19, 19]
});
+ window.loadedTiles = new Set();
+ window.loadTiles = (map) => {
+ var layerGroup = L.layerGroup().addTo(map);
+ var dl_places = () => {
+ const zoom = map.getZoom();
+ if (zoom < 12) {
+ if (map.hasLayer(layerGroup))
+ map.removeLayer(layerGroup);
+ return;
+ }
+ else
+ if (!map.hasLayer(layerGroup)) {
+ map.addLayer(layerGroup);
+ layerGroup.bringToBack();
+ }
- window.other_markers = [];
- {% with cache_timeout=user.is_authenticated|yesno:"300,6000" %}
- {% cache cache_timeout place_lists_js user.is_authenticated %}
+ const bounds = map.getBounds();
+ const tileSize = 0.1;
+
+ const latStart = Math.floor(bounds.getSouth() / tileSize);
+ const latEnd = Math.ceil(bounds.getNorth() / tileSize);
+ const lngStart = Math.floor(bounds.getWest() / tileSize);
+ const lngEnd = Math.ceil(bounds.getEast() / tileSize);
+
+ for (let x = lngStart; x <= lngEnd; x++) {
+ for (let y = latStart; y <= latEnd; y++) {
+ const tileKey = `${x}_${y}`;
+ if (window.loadedTiles.has(tileKey)) continue;
+
+ fetch(`/api/places/tile/?tile_x=${x}&tile_y=${y}&tile_size=${tileSize}`)
+ .then((res) => res.json())
+ .then((data) => {
+ data.forEach((place) => {
+ layerGroup.addLayer(L.marker([place.lat, place.lng], {'icon': circleIcon})
+ .bindPopup(`${place.name}`));
+ });
+ window.loadedTiles.add(tileKey);
+ });
+ }
+ }
+ };
+ map.on("moveend", dl_places);
+ dl_places();
+ };
- {% if place_list %}
- {% for place in place_list %}
- window.other_markers.push(L.marker([{{ place.location|tocoords }}], {'icon': circleIcon}).bindPopup('{{ place.name }}
{% if place.address %}{{ place.address }}, {% endif %}{{ place.city }}'));
- {% endfor %}
- {% endif %}
- {% endcache %}
- {% endwith %}