From 3fbae56cbf5f5f4ceff8ed29d101d2ade1b07f67 Mon Sep 17 00:00:00 2001 From: Jean-Marie Favreau Date: Wed, 16 Oct 2024 12:09:23 +0200 Subject: [PATCH] =?UTF-8?q?WIP:=20interface=20de=20saisie=20de=20la=20posi?= =?UTF-8?q?tion=20par=20une=20carte=20(trop=20complexe,=20abandonn=C3=A9e?= =?UTF-8?q?=20pour=20l'instant)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/agenda_culturel/models.py | 2 +- src/agenda_culturel/static/style.scss | 8 ++- .../templates/agenda_culturel/filter-inc.html | 50 +++++++++++++++-- src/agenda_culturel/views.py | 54 +++++++++++++------ 4 files changed, 91 insertions(+), 23 deletions(-) diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py index 9189a33..84d902d 100644 --- a/src/agenda_culturel/models.py +++ b/src/agenda_culturel/models.py @@ -246,7 +246,7 @@ class Place(models.Model): null=True, ) city = models.CharField(verbose_name=_("City"), help_text=_("City name")) - location = LocationField(based_fields=["name", "address", "city"], zoom=12, default=Point(3.08333, 45.783329)) + location = LocationField(based_fields=["name", "address", "city"], zoom=12, default=Point(3.08333, 45.783329), srid=4326) aliases = ArrayField( models.CharField(max_length=512), diff --git a/src/agenda_culturel/static/style.scss b/src/agenda_culturel/static/style.scss index ce218a8..884941e 100644 --- a/src/agenda_culturel/static/style.scss +++ b/src/agenda_culturel/static/style.scss @@ -130,6 +130,10 @@ details[role="list"] summary + ul li.selected>a:hover { display: none; } } + // on les cache pour le cas où il n'y a pas de js + .nojs, .hidden { + display: none; + } } @media (min-width: 992px) { @@ -325,7 +329,7 @@ footer [data-tooltip] { text-align: center; position: fixed; top: 65vh; - z-index: 10; + z-index: 1000; opacity: 0.9; a { color: var(--primary-inverse); @@ -1249,4 +1253,4 @@ form.messages div { display: inline-block; margin-right: 1em; } -} \ No newline at end of file +} diff --git a/src/agenda_culturel/templates/agenda_culturel/filter-inc.html b/src/agenda_culturel/templates/agenda_culturel/filter-inc.html index 2fd8837..340ae7f 100644 --- a/src/agenda_culturel/templates/agenda_culturel/filter-inc.html +++ b/src/agenda_culturel/templates/agenda_culturel/filter-inc.html @@ -1,6 +1,7 @@ {% load cat_extra %} {% load tag_extra %} {% load utils_extra %} +{% load static %} {% if not noarticle %}
@@ -23,9 +24,9 @@ {% for s in filter.get_status_names %} {{ s }} {% endfor %} - {% for c in filter.get_cities %} - {{ c }} - {% endfor %} + {% if filter.get_position %} + {% picto_from_name "map-pin" %} + {% endif %} {{ filter.get_recurrence_filtering }} {% else %} Autres filtres @@ -37,8 +38,47 @@
- {{ filter.form.as_p }} - +
+
+ {% for f in filter.form.visible_fields %} + {% if f.id_for_label and f.id_for_label in "id_position_filter,id_position_map,id_position_gps" %} + + {% endif %} + {% endfor %} +
+ {{ form.media }} + {% for f in filter.form.visible_fields %} + {% if not f.id_for_label or not f.id_for_label in "id_position_filter,id_position_map,id_position_gps" %} +

+ {{ f.errors }} + {{ f.label_tag }} {{ f }} + {{ f.help_text }} +

+ {% endif %} + {% endfor %} + + + + +
diff --git a/src/agenda_culturel/views.py b/src/agenda_culturel/views.py index 330ac21..8ef6693 100644 --- a/src/agenda_culturel/views.py +++ b/src/agenda_culturel/views.py @@ -11,10 +11,15 @@ from django import forms from django.contrib.postgres.search import SearchQuery, SearchHeadline from django.utils.safestring import mark_safe +from django.contrib.gis.geos import Point +from django.contrib.gis.measure import D + from django.http import HttpResponseRedirect, HttpResponse from django.urls import reverse from collections import Counter +from location_field.widgets import LocationWidget + from django.forms import formset_factory from .forms import ( @@ -32,7 +37,8 @@ from .forms import ( CategorisationForm, EventAddPlaceForm, PlaceForm, - MultipleHiddenInput + MultipleHiddenInput, + HiddenInput ) from .models import ( @@ -170,6 +176,21 @@ class EventFilter(django_filters.FilterSet): ("only_recurrent", "Montrer uniquement les événements récurrents"), ] + position_filter = django_filters.CharFilter( + label="Filtrer par position", + method="filter_position", + help_text="Format: latitude,longitude,distance (km). Exemple: 45.783329,3.08333,3" + ) + + position_gps = django_filters.CharFilter( + label="Recherche par adresse", + ) + + position_map = django_filters.CharFilter( + label="Position sur la carte", + widget=LocationWidget(based_fields=['position_gps']) + ) + exclude_tags = django_filters.MultipleChoiceFilter( label="Exclure les étiquettes", choices=[(t, t) for t in Event.get_all_tags()], @@ -201,13 +222,6 @@ class EventFilter(django_filters.FilterSet): widget=MultipleHiddenInput, ) - city = django_filters.MultipleChoiceFilter( - label="Filtrer par ville", - field_name="exact_location__city", - choices=[(c, c) for c in Place.get_all_cities()], - widget=forms.CheckboxSelectMultiple, - ) - status = django_filters.MultipleChoiceFilter( label="Filtrer par status", choices=Event.STATUS.choices, @@ -217,13 +231,22 @@ class EventFilter(django_filters.FilterSet): class Meta: model = Event - fields = ["category", "city", "tags", "exclude_tags", "status", "recurrences"] + fields = ["category", "tags", "exclude_tags", "status", "recurrences"] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if not kwargs["request"].user.is_authenticated: self.form.fields.pop("status") + def filter_position(self, queryset, name, value): + values = value.split(',') + if len(values) != 3: + return queryset + else: + p = Point(float(values[1]), float(values[0]), srid=4326) + d = float(values[2]) + return queryset.exclude(exact_location=False).filter(exact_location__location__distance_lt=(p, D(km=d))) + def filter_recurrences(self, queryset, name, value): # construct the full lookup expression lookup = "__".join([name, "isnull"]) @@ -296,12 +319,13 @@ class EventFilter(django_filters.FilterSet): def get_status(self): return self.get_cleaned_data("status") - def get_cities(self): - return self.get_cleaned_data("city") + def get_position(self): + return self.get_cleaned_data("position_filter") + def to_str(self, prefix=''): self.form.full_clean() - result = ' '.join([c.name for c in self.get_categories()] + [t for t in self.get_tags()] + [c for c in self.get_cities()]) + result = ' '.join([c.name for c in self.get_categories()] + [t for t in self.get_tags()] + [t for t in self.get_exclude_tags()] + [p for p in self.get_position()]) if len(result) > 0: result = prefix + result return result @@ -346,7 +370,7 @@ class EventFilter(django_filters.FilterSet): len(self.get_cleaned_data("tags")) != 0 or len(self.get_cleaned_data("exclude_tags")) != 0 or len(self.get_cleaned_data("recurrences")) != 0 - or len(self.get_cleaned_data("city")) != 0 + or len(self.get_cleaned_data("position_filter")) != 0 ) def is_active(self, only_categories=False): @@ -361,7 +385,7 @@ class EventFilter(django_filters.FilterSet): len(self.get_cleaned_data("tags")) != 0 or len(self.get_cleaned_data("exclude_tags")) != 0 or len(self.get_cleaned_data("recurrences")) != 0 - or len(self.get_cleaned_data("city")) != 0 + or len(self.get_cleaned_data("position_filter")) != 0 ) def is_selected(self, cat): @@ -1889,7 +1913,7 @@ class PlaceUpdateView( class PlaceCreateView( - UpdatePlaces, PermissionRequiredMixin, SuccessMessageMixin, CreateView + UpdatePlaces, SuccessMessageMixin, CreateView ): model = Place permission_required = "agenda_culturel.add_place"