From 51fa31b44d7cb47d6fe0067d09935b788212ef08 Mon Sep 17 00:00:00 2001
From: Serghei Mihai <smihai@entrouvert.com>
Date: Wed, 5 Jun 2019 10:31:14 +0200
Subject: [PATCH] forms: decorate "nearby" field (#33680)

---
 static/includes/_wcs.scss                     |  67 ++++++++++++
 static/js/plus1.js                            | 102 ++++++++++++++++++
 .../qommon/forms/widgets/nearby-forms.html    |  55 ++++++++++
 3 files changed, 224 insertions(+)
 create mode 100644 static/js/plus1.js
 create mode 100644 templates/qommon/forms/widgets/nearby-forms.html

diff --git a/static/includes/_wcs.scss b/static/includes/_wcs.scss
index abb4a978f..91404c731 100644
--- a/static/includes/_wcs.scss
+++ b/static/includes/_wcs.scss
@@ -760,3 +760,70 @@ div.section.foldable {
 		}
 	}
 }
+
+#nearby-forms {
+	margin: 0;
+	padding: 0;
+	li {
+		margin: 5px auto;
+		display: -ms-flexbox;
+		display: flex;
+		-ms-align-items: center;
+		-ms-flex-align: center;
+		align-items: center;
+		-ms-flex-line-pack: center;
+		align-content: center;
+		-ms-flex-pack: space-between;
+		-ms-justify-content: space-between;
+		justify-content: space-between;
+		border: $widget-border;
+		padding: 5px;
+	}
+	span {
+		margin: 0 5px;
+		&.form-digest {
+			width: 60%;
+		}
+		&.form-datetime {
+			width: 20%;
+			@media screen and (max-width: $mobile-limit) {
+				width: 30%;
+			}
+		}
+		&.marker-counter {
+			background: $button-background;
+			padding: 5px 10px;
+			color: $button-color;
+			min-width: 0.5em;
+			max-width: 1em;
+			border-radius: 3px;
+		}
+	}
+}
+.template-nearby-forms div.leaflet-div-icon {
+	padding: 3px;
+	margin: auto;
+	border-radius: 3px;
+	display: -ms-flexbox;
+	display: flex;
+	a {
+		line-height: 1;
+		margin: auto;
+	}
+}
+
+.signalements-thanks ~ .buttons {
+	.submit-button, .previous-button {
+		display: none;
+	}
+	.cancel-button button {
+		text-indent: -9999px;
+		line-height: 0;
+		&::after {
+			text-indent: 0;
+			line-height: initial;
+			display: block;
+			content: 'Continuer';
+		}
+	}
+}
diff --git a/static/js/plus1.js b/static/js/plus1.js
new file mode 100644
index 000000000..c7247c643
--- /dev/null
+++ b/static/js/plus1.js
@@ -0,0 +1,102 @@
+$(function() {
+  function user_is_authenticated() {
+    return $('body').is('.authenticated-user');
+  }
+  var nearby_list = $('#nearby-forms');
+  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 = [];
+      nearby_list.find('li[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 */
+        nearby_list.find('li').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('li[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');
+      }
+      $('button.plus1').on('click', function() {
+        var plus1_url = $(this).data('plus1-url');
+        var $dialog = null;
+        if (user_is_authenticated()) {
+          $dialog = $('<div id="plus1-dialog">'
+                      + '<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>'
+                      + '</div>');
+        } else {
+          $dialog = $('<div id="plus1-dialog">'
+                      + '<p>Vous allez confirmer le signalement.</p>'
+                      + '</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;
+      });
+    });
+  }
+})
diff --git a/templates/qommon/forms/widgets/nearby-forms.html b/templates/qommon/forms/widgets/nearby-forms.html
new file mode 100644
index 000000000..26e4bcfad
--- /dev/null
+++ b/templates/qommon/forms/widgets/nearby-forms.html
@@ -0,0 +1,55 @@
+{% extends "qommon/forms/widgets/map.html" %}
+{% load qommon l10n static %}
+
+{% 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 %}
+<ul id="nearby-forms">
+  {% with distance=form_option_distance|default:100|add:50 %}
+  {% with demands=form.objects.pending|distance_filter:distance %}
+  {% for formdata in demands %}
+      <li data-id="{{formdata.number}}"
+           {% localize off %}
+           data-geoloc-lat="{{formdata.geoloc.base.lat}}"
+           data-geoloc-lon="{{formdata.geoloc.base.lon}}"
+           {% endlocalize %}
+           >
+              <span class="marker-counter" id="nearby-{{forloop.counter}}">{{forloop.counter}}</span>
+              {% block problem-digest %}
+              <span class="form-digest">{{ formdata.digest }}</span>
+              {% endblock %}
+              <span class="form-datetime">Signalé le <time datetime="{{ formdata.receipt_date|datetime|date:"c" }}">{{ formdata.receipt_date }}</time></span>
+              {% if activate_plus1_action == "True" %}
+              <button class="plus1" href="#" data-plus1-url="{{formdata.api_url}}hooks/plus1/" aria-label="Même signalement">+1</button>
+              {% endif %}
+      </li>
+  {% endfor %}
+{% endwith %}
+{% endwith %}
+</ul>
+<script src="{% static 'xstatic/jquery-ui.js' %}"></script>
+<script src="{% static "js/plus1.js" %}"></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

