WIP: interface de saisie de la position par une carte (trop complexe, abandonnée
pour l'instant)
This commit is contained in:
parent
fba52afbb0
commit
3fbae56cbf
@ -246,7 +246,7 @@ class Place(models.Model):
|
|||||||
null=True,
|
null=True,
|
||||||
)
|
)
|
||||||
city = models.CharField(verbose_name=_("City"), help_text=_("City name"))
|
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(
|
aliases = ArrayField(
|
||||||
models.CharField(max_length=512),
|
models.CharField(max_length=512),
|
||||||
|
@ -130,6 +130,10 @@ details[role="list"] summary + ul li.selected>a:hover {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// on les cache pour le cas où il n'y a pas de js
|
||||||
|
.nojs, .hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
@media (min-width: 992px) {
|
||||||
@ -325,7 +329,7 @@ footer [data-tooltip] {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 65vh;
|
top: 65vh;
|
||||||
z-index: 10;
|
z-index: 1000;
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
a {
|
a {
|
||||||
color: var(--primary-inverse);
|
color: var(--primary-inverse);
|
||||||
@ -1249,4 +1253,4 @@ form.messages div {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{% load cat_extra %}
|
{% load cat_extra %}
|
||||||
{% load tag_extra %}
|
{% load tag_extra %}
|
||||||
{% load utils_extra %}
|
{% load utils_extra %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
{% if not noarticle %}
|
{% if not noarticle %}
|
||||||
<article id="filters">
|
<article id="filters">
|
||||||
@ -23,9 +24,9 @@
|
|||||||
{% for s in filter.get_status_names %}
|
{% for s in filter.get_status_names %}
|
||||||
{{ s }}
|
{{ s }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% for c in filter.get_cities %}
|
{% if filter.get_position %}
|
||||||
{{ c }}
|
<span data-tooltip="{{ filter.get_position }}">{% picto_from_name "map-pin" %}</span>
|
||||||
{% endfor %}
|
{% endif %}
|
||||||
{{ filter.get_recurrence_filtering }}
|
{{ filter.get_recurrence_filtering }}
|
||||||
{% else %}
|
{% else %}
|
||||||
Autres filtres
|
Autres filtres
|
||||||
@ -37,8 +38,47 @@
|
|||||||
|
|
||||||
</summary>
|
</summary>
|
||||||
<form method="get" class="form django-form main-filter">
|
<form method="get" class="form django-form main-filter">
|
||||||
{{ filter.form.as_p }}
|
<div class="map-widget">
|
||||||
<button type="submit">Appliquer le filtre</button>
|
<div id="map_position_map" style="width: 100%; height: 50vh;" class="nojs"></div>
|
||||||
|
{% 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" %}
|
||||||
|
<div {% if f.id_for_label == "id_position_map" %}
|
||||||
|
class="hidden"
|
||||||
|
{% else %}
|
||||||
|
{% if f.id_for_label == "id_position_gps" %}
|
||||||
|
class="nojs"
|
||||||
|
{% else %}
|
||||||
|
class="withjs"
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
>
|
||||||
|
{{ f.errors }}
|
||||||
|
{{ f.label_tag }} {{ f }}
|
||||||
|
<span class="helptext">{{ f.help_text }}</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{{ 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" %}
|
||||||
|
<p>
|
||||||
|
{{ f.errors }}
|
||||||
|
{{ f.label_tag }} {{ f }}
|
||||||
|
<span class="helptext">{{ f.help_text }}</span>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<button type="submit">Appliquer le filtre</button>
|
||||||
|
<script src="/static/admin/js/vendor/jquery/jquery.js"></script>
|
||||||
|
<script src="/static/admin/js/jquery.init.js"></script>
|
||||||
|
<script src="/static/location_field/js/form.js"></script>
|
||||||
|
<script>
|
||||||
|
document.querySelectorAll('.nojs').forEach(function(item) {
|
||||||
|
item.classList.remove('nojs'); });
|
||||||
|
document.querySelectorAll('.withjs').forEach(function(item) {
|
||||||
|
item.classList.add('nojs'); });
|
||||||
|
</script>
|
||||||
</form>
|
</form>
|
||||||
</details>
|
</details>
|
||||||
<div class="clear"></div>
|
<div class="clear"></div>
|
||||||
|
@ -11,10 +11,15 @@ from django import forms
|
|||||||
from django.contrib.postgres.search import SearchQuery, SearchHeadline
|
from django.contrib.postgres.search import SearchQuery, SearchHeadline
|
||||||
from django.utils.safestring import mark_safe
|
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.http import HttpResponseRedirect, HttpResponse
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
|
|
||||||
|
from location_field.widgets import LocationWidget
|
||||||
|
|
||||||
from django.forms import formset_factory
|
from django.forms import formset_factory
|
||||||
|
|
||||||
from .forms import (
|
from .forms import (
|
||||||
@ -32,7 +37,8 @@ from .forms import (
|
|||||||
CategorisationForm,
|
CategorisationForm,
|
||||||
EventAddPlaceForm,
|
EventAddPlaceForm,
|
||||||
PlaceForm,
|
PlaceForm,
|
||||||
MultipleHiddenInput
|
MultipleHiddenInput,
|
||||||
|
HiddenInput
|
||||||
)
|
)
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
@ -170,6 +176,21 @@ class EventFilter(django_filters.FilterSet):
|
|||||||
("only_recurrent", "Montrer uniquement les événements récurrents"),
|
("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(
|
exclude_tags = django_filters.MultipleChoiceFilter(
|
||||||
label="Exclure les étiquettes",
|
label="Exclure les étiquettes",
|
||||||
choices=[(t, t) for t in Event.get_all_tags()],
|
choices=[(t, t) for t in Event.get_all_tags()],
|
||||||
@ -201,13 +222,6 @@ class EventFilter(django_filters.FilterSet):
|
|||||||
widget=MultipleHiddenInput,
|
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(
|
status = django_filters.MultipleChoiceFilter(
|
||||||
label="Filtrer par status",
|
label="Filtrer par status",
|
||||||
choices=Event.STATUS.choices,
|
choices=Event.STATUS.choices,
|
||||||
@ -217,13 +231,22 @@ class EventFilter(django_filters.FilterSet):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Event
|
model = Event
|
||||||
fields = ["category", "city", "tags", "exclude_tags", "status", "recurrences"]
|
fields = ["category", "tags", "exclude_tags", "status", "recurrences"]
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
if not kwargs["request"].user.is_authenticated:
|
if not kwargs["request"].user.is_authenticated:
|
||||||
self.form.fields.pop("status")
|
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):
|
def filter_recurrences(self, queryset, name, value):
|
||||||
# construct the full lookup expression
|
# construct the full lookup expression
|
||||||
lookup = "__".join([name, "isnull"])
|
lookup = "__".join([name, "isnull"])
|
||||||
@ -296,12 +319,13 @@ class EventFilter(django_filters.FilterSet):
|
|||||||
def get_status(self):
|
def get_status(self):
|
||||||
return self.get_cleaned_data("status")
|
return self.get_cleaned_data("status")
|
||||||
|
|
||||||
def get_cities(self):
|
def get_position(self):
|
||||||
return self.get_cleaned_data("city")
|
return self.get_cleaned_data("position_filter")
|
||||||
|
|
||||||
|
|
||||||
def to_str(self, prefix=''):
|
def to_str(self, prefix=''):
|
||||||
self.form.full_clean()
|
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:
|
if len(result) > 0:
|
||||||
result = prefix + result
|
result = prefix + result
|
||||||
return result
|
return result
|
||||||
@ -346,7 +370,7 @@ class EventFilter(django_filters.FilterSet):
|
|||||||
len(self.get_cleaned_data("tags")) != 0
|
len(self.get_cleaned_data("tags")) != 0
|
||||||
or len(self.get_cleaned_data("exclude_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("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):
|
def is_active(self, only_categories=False):
|
||||||
@ -361,7 +385,7 @@ class EventFilter(django_filters.FilterSet):
|
|||||||
len(self.get_cleaned_data("tags")) != 0
|
len(self.get_cleaned_data("tags")) != 0
|
||||||
or len(self.get_cleaned_data("exclude_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("recurrences")) != 0
|
||||||
or len(self.get_cleaned_data("city")) != 0
|
or len(self.get_cleaned_data("position_filter")) != 0
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_selected(self, cat):
|
def is_selected(self, cat):
|
||||||
@ -1889,7 +1913,7 @@ class PlaceUpdateView(
|
|||||||
|
|
||||||
|
|
||||||
class PlaceCreateView(
|
class PlaceCreateView(
|
||||||
UpdatePlaces, PermissionRequiredMixin, SuccessMessageMixin, CreateView
|
UpdatePlaces, SuccessMessageMixin, CreateView
|
||||||
):
|
):
|
||||||
model = Place
|
model = Place
|
||||||
permission_required = "agenda_culturel.add_place"
|
permission_required = "agenda_culturel.add_place"
|
||||||
|
Loading…
Reference in New Issue
Block a user