Parcourir la source

Merge branch 'django' of ssh://code.ffdn.org:55555/FFDN/wifi-with-me into django

CapsLock il y a 9 ans
Parent
commit
1ef0a3c228

+ 3 - 1
.gitignore

@@ -4,4 +4,6 @@ __pycache__/
 *.sqlite3
 wifiwithme/settings/local.py
 var/media/*
-var/static/*
+var/static/*
+venv
+.idea

+ 35 - 0
wifiwithme/apps/contribmap/forms.py

@@ -55,6 +55,35 @@ class PublicContribForm(forms.ModelForm):
         'privacy_place_details', 'privacy_comment',
     )
 
+    def _validate_contact_information(self, data):
+        if (data.get('phone') == '') and (data.get('email') == ''):
+            msg = 'Il faut remplir un des deux champs "téléphone" ou "email".'
+            self.add_error('phone', msg)
+            self.add_error('email', msg)
+
+    def _validate_floors(self, data):
+        if None in (data.get('floor'), data.get('floor_total')):
+            return
+
+        if (data.get('floor') > data.get('floor_total')):
+            self.add_error(
+                'floor',
+                "L'étage doit être inférieur ou égal au nombre d'étages",
+            )
+
+    def _validate_share_fields(self, data):
+        if data.get('contrib_type') == Contrib.CONTRIB_SHARE:
+            for required_field in ('access_type', 'bandwidth', 'share_part'):
+                if data.get(required_field, '') is None:
+                    self.add_error(required_field, 'Ce champ est requis')
+
+    def clean(self):
+        cleaned_data = super().clean()
+        self._validate_contact_information(cleaned_data)
+        self._validate_floors(cleaned_data)
+        self._validate_share_fields(cleaned_data)
+        return cleaned_data
+
     def privacy_fields(self):
         for i in self._privacy_fieldnames:
             field = self[i]
@@ -64,3 +93,9 @@ class PublicContribForm(forms.ModelForm):
                                .replace('public', '')\
                                .replace('publiques', '')
             yield field
+
+    def __init__(self, *args, **kwargs):
+        super(PublicContribForm, self).__init__(*args, **kwargs)
+
+        for f in ['latitude', 'longitude']:
+            self.fields[f].error_messages['required'] = "Veuillez déplacer le curseur à l'endroit où vous voulez partager/accéder au service"

+ 36 - 0
wifiwithme/apps/contribmap/migrations/0012_auto_20160510_2335.py

@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('contribmap', '0011_auto_20160316_1623'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='contrib',
+            name='contrib_type',
+            field=models.CharField(default=None, verbose_name='Type de contribution', choices=[('connect', 'Me raccorder au réseau expérimental'), ('share', 'Partager une partie de ma connexion')], max_length=10),
+        ),
+        migrations.AlterField(
+            model_name='contrib',
+            name='latitude',
+            field=models.FloatField(default=0),
+            preserve_default=False,
+        ),
+        migrations.AlterField(
+            model_name='contrib',
+            name='longitude',
+            field=models.FloatField(default=0),
+            preserve_default=False,
+        ),
+        migrations.AlterField(
+            model_name='contrib',
+            name='status',
+            field=models.CharField(null=True, blank=True, default='TOSTUDY', choices=[('TOSTUDY', 'à étudier'), ('TOCONNECT', 'à connecter'), ('CONNECTED', 'connecté'), ('WONTCONNECT', 'pas connectable')], max_length=250),
+        ),
+    ]

+ 3 - 3
wifiwithme/apps/contribmap/models.py

@@ -22,8 +22,8 @@ class Contrib(models.Model):
             (CONTRIB_CONNECT, 'Me raccorder au réseau expérimental'),
             (CONTRIB_SHARE, 'Partager une partie de ma connexion')
         ), default=None)
-    latitude = models.FloatField(blank=True, null=True)
-    longitude = models.FloatField(blank=True, null=True)
+    latitude = models.FloatField()
+    longitude = models.FloatField()
     phone = models.CharField(
         'Téléphone',
         max_length=30, blank=True, default='')
@@ -134,7 +134,7 @@ class Contrib(models.Model):
         return merge_intervals(angles)
 
     def is_public(self):
-        return not self.privacy_coordinates
+        return self.privacy_coordinates
 
     def _may_be_public(self, field):
         return field in self.PUBLIC_FIELDS

+ 12 - 6
wifiwithme/apps/contribmap/templates/contribmap/map.html

@@ -1,17 +1,23 @@
-%rebase base page='map'
+{% extends "base.html" %}
+
+{% load staticfiles %}
 
 <!-- <span class="back-link">&larr; <a href="/">Accueil</a></span> -->
 
+
+{% block content %}
 <h1>Résultats</h1>
 
-<div id="map" class="results" data-json="{{geojson}}"></div>
-<script src="assets/map.js" type="text/javascript"></script>
+<div id="map" class="results" data-json="{% url 'public_json' %}"></div>
+<script src="{% static 'map.js' %}" type="text/javascript"></script>
 <p>Légende : <br />
-  <img src="assets/leaflet/images/marker-icon-red.png" /> Personne souhaitant partager sa connexion Internet<br />
-  <img src="assets/leaflet/images/marker-icon.png" /> Personne souhaitant se connecter au réseau radio
+  <img src="{% static 'leaflet/images/marker-icon-red.png' %}" /> Personne souhaitant partager sa connexion Internet<br />
+  <img src="{% static 'leaflet/images/marker-icon.png' %}" /> Personne souhaitant se connecter au réseau radio
 </p>
 <p>
-  Télécharger le fichier <a href="{{geojson}}">GeoJSON</a> (base de données mise sous
+  Télécharger le fichier <a href="{% url 'public_json' %}">GeoJSON</a> (base de données mise sous
   licence <a href="http://opendatacommons.org/licenses/by/summary/">ODC-BY
   1.0</a>).
 </p>
+
+{% endblock content %}

+ 3 - 1
wifiwithme/apps/contribmap/templates/contribmap/thanks.html

@@ -1,5 +1,7 @@
 {% extends "base.html" %}
 
+{% load staticfiles %}
+
 {% block content %}
 
 <h1>Merci !</h1>
@@ -16,7 +18,7 @@ l'association.
 </p>
 
 <p>
-Vous pouvez consulter la <a href="./map">carte publique avec tous les autres contributions</a>.
+Vous pouvez consulter la <a href="{% url 'display_map' %}">carte publique avec tous les autres contributions</a>.
 </p>
 
 {% endblock %}

+ 3 - 3
wifiwithme/apps/contribmap/templates/contribmap/wifi-form.html

@@ -1,3 +1,4 @@
+
 {% extends "base.html" %}
 
 {% load bootstrap %}
@@ -140,9 +141,8 @@ pourraient être intéressantes.
 
         </div>
         {{ form.latitude }}
-        {{ form.latitude.errors }}
         {{ form.longitude }}
-        {{ form.longitude.errors }}
+        {% firstof form.latitude.errors form.latitude.errors %}
         </div>
       </div>
 
@@ -172,7 +172,7 @@ pourraient être intéressantes.
     <div class="form-inline col-md-6">
       <label for="floor">Mon étage</label>
       {{ form.floor }}
-      {{ form.phone.errors }}
+      {{ form.floor.errors }}
       /
       {{ form.floor_total }}
       {{ form.floor_total.errors }}

+ 60 - 0
wifiwithme/apps/contribmap/tests.py

@@ -5,6 +5,7 @@ from django.contrib.auth.models import User
 from django.test import TestCase, Client, override_settings
 
 from contribmap.models import Contrib
+from contribmap.forms import PublicContribForm
 
 
 class APITestClient(Client):
@@ -132,6 +133,65 @@ class TestViews(APITestCase):
         self.assertIn('JohnCleese', mail.outbox[0].subject)
         self.assertIn('JohnCleese', mail.outbox[0].body)
 
+class TestForms(TestCase):
+    valid_data = {
+        'roof': True,
+        'privacy_place_details': True,
+        'privacy_coordinates': True,
+        'orientations': ['N'],
+        'orientation': 'all',
+        'name': 'JohnCleese',
+        'longitude': -1.553621,
+        'email': 'foo@example.com',
+        'phone': '0202020202',
+        'latitude': 47.218371,
+        'floor_total': '2',
+        'floor': 1,
+        'contrib_type': 'connect',
+        'connect_local': 'on',
+    }
+
+    def test_contact_validation(self):
+        no_contact, phone_contact, email_contact, both_contact = [
+            self.valid_data.copy() for i in range(4)]
+
+        del phone_contact['email']
+        del email_contact['phone']
+        del no_contact['phone']
+        del no_contact['email']
+
+        both_contact.update(phone_contact)
+        both_contact.update(email_contact)
+
+        self.assertFalse(PublicContribForm(no_contact).is_valid())
+        self.assertTrue(PublicContribForm(phone_contact).is_valid())
+        self.assertTrue(PublicContribForm(email_contact).is_valid())
+        self.assertTrue(PublicContribForm(both_contact).is_valid())
+
+    def test_floors_validation(self):
+        invalid_floors = self.valid_data.copy()
+        invalid_floors['floor'] = 2
+        invalid_floors['floor_total'] = 1
+
+        self.assertFalse(PublicContribForm(invalid_floors).is_valid())
+        self.assertTrue(PublicContribForm(self.valid_data).is_valid())
+
+        invalid_floors['floor'] = None
+        invalid_floors['floor_total'] = None
+        self.assertTrue(PublicContribForm(invalid_floors).is_valid())
+
+    def test_share_fields_validation(self):
+        data = self.valid_data.copy()
+        data['contrib_type'] = 'share'
+
+        self.assertFalse(PublicContribForm(data).is_valid())
+        data['access_type'] = 'cable'
+        self.assertFalse(PublicContribForm(data).is_valid())
+        data['bandwidth'] = 12
+        self.assertFalse(PublicContribForm(data).is_valid())
+        data['share_part'] = 5
+        self.assertTrue(PublicContribForm(data).is_valid())
+
 
 class TestDataImport(TestCase):
     fixtures = ['bottle_data.yaml']

+ 2 - 1
wifiwithme/apps/contribmap/urls.py

@@ -1,8 +1,9 @@
 from django.conf.urls import url
 
-from .views import PublicJSON, PrivateJSON, add_contrib, thanks
+from .views import PublicJSON, PrivateJSON, display_map, add_contrib, thanks
 
 urlpatterns = [
+    url(r'^$', display_map, name='display_map'),
     url(r'^contribute/thanks', thanks, name='thanks'),
     url(r'^contribute', add_contrib, name='add_contrib'),
     url(r'^public.json$', PublicJSON.as_view(), name='public_json'),

+ 5 - 2
wifiwithme/apps/contribmap/views.py

@@ -44,6 +44,10 @@ def add_contrib(request):
     })
 
 
+def display_map(request):
+    return render(request, 'contribmap/map.html')
+
+
 def thanks(request):
     return render(request, 'contribmap/thanks.html')
 
@@ -74,14 +78,13 @@ class PublicJSON(JSONContribView):
         for i in contribs:
             if not i.is_public():
                 continue
-
             data.append({
                 "id": i.pk,
                 "type": "Feature",
                 "geometry": {
                     "coordinates": [
-                        i.latitude,
                         i.longitude,
+                        i.latitude
                     ],
                     "type": "Point",
                 },

+ 5 - 2
wifiwithme/core/urls.py

@@ -1,7 +1,10 @@
+from django.conf import settings
 from django.conf.urls import url, include
 from django.contrib import admin
 
+prefix = settings.URL_PREFIX
+
 urlpatterns = [
-    url(r'^admin/', admin.site.urls),
-    url(r'^map/', include('contribmap.urls')),
+    url(r'^{}admin/'.format(prefix), admin.site.urls),
+    url(r'^{}map/'.format(prefix), include('contribmap.urls')),
 ]

+ 3 - 3
wifiwithme/settings/base.py

@@ -119,12 +119,12 @@ USE_TZ = True
 
 ## URL Prefixing
 
-URL_PREFIX='/'
+URL_PREFIX=''
 
 # Static files (CSS, JavaScript, Images)
 # https://docs.djangoproject.com/en/1.9/howto/static-files/
-
-STATIC_URL = URL_PREFIX + 'assets/'
+# STATIC_URL = '/{}assets/'.format(URL_PREFIX)
+# not defined here cause prefix overriding would not be taken into account
 
 STATICFILES_DIRS = [
     os.path.join(BASE_DIR, "static"),

+ 1 - 0
wifiwithme/settings/dev.py

@@ -11,3 +11,4 @@ except ImportError:
     pass
 
 EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
+STATIC_URL = '/{}assets/'.format(URL_PREFIX)

+ 2 - 0
wifiwithme/settings/prod.py

@@ -9,3 +9,5 @@ try:
     from .local import *
 except ImportError:
     pass
+
+STATIC_URL = '/{}assets/'.format(URL_PREFIX)

+ 5 - 4
wifiwithme/static/form.js

@@ -22,16 +22,17 @@ $( document ).ready(function() {
         maxWidth: 150
     }).addTo(map);
 
-    // Create marker
-    var marker = L.marker([defaults.lat,defaults.lng], {
+    var marker = L.marker([defaults.lat, defaults.lng], {
         draggable: true
     }).addTo(map);
 
     // every time the marker is dragged, update the coordinates container
     marker.on('dragend', mapUpdateCoords);
 
-    // Set the initial marker coordinate on load.
-    mapUpdateCoords();
+    map.on('click', (e) => {
+        marker.setLatLng(e.latlng)
+        mapUpdateCoords()
+    });
 
     function mapUpdateCoords() {
         var m = marker.getLatLng();

+ 8 - 2
wifiwithme/static/main.css

@@ -81,14 +81,20 @@ form > h2:first-child {
     border: 1px solid #a94442;
     border-radius: 4px;
 }
+
+/* non-field errorfields */
+#errors ul.errorlist {
+  border: 0;
+}
+
 #errors ul {
     margin: 0 0 0 1em;
     padding: 0;
 }
 
-.form-group .errorlist{
+ .errorlist {
   list-style-type: none;
-}
+ }
 
 /** Results **/
 #map.results {

+ 2 - 2
wifiwithme/static/map.js

@@ -9,7 +9,7 @@ $( document ).ready(function() {
 
     // Icons
     var leecherIcon = L.icon({
-    iconUrl: 'assets/leaflet/images/marker-icon.png',
+    iconUrl: '../assets/leaflet/images/marker-icon.png',
         iconSize: [25, 41],
         iconAnchor: [12, 41],
         popupAnchor: [0, -28]
@@ -17,7 +17,7 @@ $( document ).ready(function() {
 
 
     var seederIcon = L.icon({
-    iconUrl: 'assets/leaflet/images/marker-icon-red.png',
+    iconUrl: '../assets/leaflet/images/marker-icon-red.png',
         iconSize: [25, 41],
         iconAnchor: [12, 41],
         popupAnchor: [0, -28]