From b41d76eea36a1f940be10d7d0f4dc17618f06040 Mon Sep 17 00:00:00 2001
From: Serghei Mihai <smihai@entrouvert.com>
Date: Tue, 10 Sep 2019 10:23:12 +0200
Subject: [PATCH] forms: decorate "nearby" field (#33680)

---
 static/includes/_wcs.scss                     |  56 +++++++
 .../forms/widgets/map--nearby-list.html       | 149 +++++++++++++++++-
 2 files changed, 203 insertions(+), 2 deletions(-)

diff --git a/static/includes/_wcs.scss b/static/includes/_wcs.scss
index 53ce35ad..5a043a20 100644
--- a/static/includes/_wcs.scss
+++ b/static/includes/_wcs.scss
@@ -761,3 +761,59 @@ div.section.foldable {
 		}
 	}
 }
+
+div#nearby-list {
+	> div {
+		margin: 5px auto;
+		display: flex;
+		align-items: center;
+		align-content: center;
+		justify-content: space-between;
+		border: $widget-border;
+		padding: 5px;
+	}
+	span {
+		margin: 0 5px;
+	}
+	a {
+		&.marker-counter {
+			background: $button-background;
+			padding: 5px 10px;
+			color: white;
+			min-width: 0.5em;
+			border-radius: 3px;
+		}
+		&.plus1 {
+			transition: all ease 0.2s;
+			&:hover {
+				background: lighten($primary-color, 10);
+			}
+		}
+	}
+}
+
+div.leaflet-div-icon {
+	padding: 3px;
+	border-radius: 3px;
+	display: flex;
+	justify-content: space-around;
+	a {
+		line-height: 1em;
+	}
+}
+
+.signalements-thanks ~ div.buttons {
+	div.submit-button, div.previous-button {
+		display: none;
+	}
+	div.cancel-button button {
+		text-indent: -9999px;
+		line-height: 0;
+		&::after {
+			text-indent: 0;
+			line-height: initial;
+			display: block;
+			content: 'Continuer';
+		}
+	}
+}
diff --git a/templates/qommon/forms/widgets/map--nearby-list.html b/templates/qommon/forms/widgets/map--nearby-list.html
index 75d14007..7933e915 100644
--- a/templates/qommon/forms/widgets/map--nearby-list.html
+++ b/templates/qommon/forms/widgets/map--nearby-list.html
@@ -1,4 +1,149 @@
 {% extends "qommon/forms/widgets/map.html" %}
-{% block  widget-control %}
-{{ block.super }}
+{% load qommon l10n %}
+
+{% block widget-title %}
 {% endblock %}
+
+{% block widget-content %}
+{% if form %}
+<input type="hidden" name="{{widget.name}}$latlng">
+<div id="map-{{widget.name}}" class="qommon-map"
+  data-readonly="true"
+  {% for key, value in widget.map_attributes.items %}{{key}}="{{value}}" {% endfor %}
+  {% localize off %}
+  data-init-lat="{{ form_var_carte_lat }}"
+  data-init-lng="{{ form_var_carte_lon }}"
+  {% endlocalize %}
+></div>
+{% block list-header %}
+  <h3>Si votre signalement ne figure pas dans la liste ci-dessous, continuez</h3>
+{% endblock %}
+<div id="nearby-list">
+  {% with distance=form_option_distance|default:100|add:50 %}
+  {% with demands=form.objects.pending|distance_filter:distance %}
+  {% for formdata in demands %}
+      <div data-id="{{formdata.number}}"
+           {% localize off %}
+           data-geoloc-lat="{{formdata.geoloc.base.lat}}"
+           data-geoloc-lon="{{formdata.geoloc.base.lon}}"
+           {% endlocalize %}
+           >
+              <a class="marker-counter" name="nearby-{{forloop.counter}}">{{forloop.counter}}</a>
+              <span class="problem-title">{{ formdata.var.problem_title }}</span>
+              <span class="problem-summary">{{ formdata.var.problem_summary }}</span>
+              <span class="problem-datetime">Signalé le {{ formdata.receipt_date }}</span>
+              <a class="plus1 pk-button" href="#" data-plus1-url="{{formdata.api_url}}hooks/plus1/">+1</a>
+      </div>
+  {% endfor %}
+{% endwith %}
+{% endwith %}
+</div>
+
+<script type="text/javascript">
+$(function() {
+  if ($('#nearby-list').length) {
+    $(document).on('wcs:maps-ready', function() {
+      var $map_widget = $('.qommon-map');
+      var map = $map_widget[0].leaflet_map;
+      var geojson_data = Array();
+      $('#nearby-list div[data-id]').each(function(idx, elem) {
+        var feature = {
+          type: 'Feature',
+          properties: {
+            id: $(elem).data('id'),
+            counter: $(elem).find('.marker-counter').text()
+          },
+          geometry: {
+            type: 'Point',
+            coordinates: [$(elem).data('geoloc-lon'), $(elem).data('geoloc-lat')]
+          }
+        };
+        geojson_data.push(feature);
+      });
+
+      $(map).on('zoomend moveend', function() {
+        /* filter display of nearby items to match the displayed map area */
+        var nearby_list = $('#nearby-list');
+        nearby_list.find('> div').hide();
+        map.eachLayer(function(layer){
+          if (layer instanceof L.Marker && map.getBounds().contains(layer.getLatLng())) {
+            if (layer.feature && layer.feature.properties.id) {
+              nearby_list.find('[data-id="' + layer.feature.properties.id + '"]').show();
+              return;
+            }
+          }
+        });
+      });
+
+      if (geojson_data) {
+        var geo_json = L.geoJson(geojson_data,
+          {
+            pointToLayer: function (feature, latlng) {
+              marker = L.divIcon({
+                                  iconAnchor: [0, 0],
+                                  popupAnchor: [5, -45],
+                                  html: '<a href="#nearby-' + feature.properties.counter + '" class="demand-map-marker">' +
+                                         feature.properties.counter + '</a>'
+                                 });
+              return L.marker(latlng, {icon: marker});
+            }
+          });
+        geo_json.addTo(map);
+        $(map).trigger('moveend');
+      }
+
+      $('a.plus1').on('click', function() {
+        var plus1_url = $(this).data('plus1-url');
+        var $dialog = null;
+        $dialog = $('<div id="plus1-dialog">'
+                    + '{% if user.is_authenticated %}<p>Vous allez confirmer le signalement.'
+                    + 'Vous pouvez également décider de recevoir un message une fois celui-ci pris en charge.</p>'
+                    + '<label><input type="checkbox">Recevoir un message</input></label>'
+                    + '{% else %}<p>Vous allez confirmer le signalement.</p>{% endif %}'
+                    + '</div>');
+        $dialog.dialog({
+          modal: true,
+          buttons: [
+                    {text: 'Annuler',
+                     'class': 'cancel-button',
+                     click: function() {
+                       $(this).dialog('destroy');
+                     }
+                    },
+                    {text: 'Confirmer',
+                     click: function() {
+                       var checked = ($(this).find('[type=checkbox]:checked').length > 0);
+                       $.ajax({
+                         url: plus1_url,
+                         data: JSON.stringify({'checked': checked}),
+                         type: 'POST',
+                         contentType: 'application/json; charset=utf-8',
+                         dataType: 'json',
+                         success: function(resp) {
+                           $dialog.dialog('destroy');
+                           $map_widget.parent().find('[type=hidden]').val('0;0');
+                           $('div.buttons button[name=submit]').click();
+                         }
+                       });
+                     }
+                    }
+                   ],
+          close: function() {}
+        });
+        return false;
+      });
+    });
+  }
+})
+</script>
+
+{% else %} {# no form, this is the admin preview #}
+<div class="infonotice">
+  {% block preview-impossible %}
+  Signalements à proximité, prévisualisation impossible.
+  {% endblock %}
+</div>
+{% endif %}
+
+{% endblock %}
+
-- 
2.23.0

