diff --git a/geotrek/tourism/forms.py b/geotrek/tourism/forms.py index a92670a311..cf5aef6169 100644 --- a/geotrek/tourism/forms.py +++ b/geotrek/tourism/forms.py @@ -4,9 +4,11 @@ from geotrek.tourism.widgets import AutoLocateMapWidget from crispy_forms.layout import Div, HTML, Fieldset +from mapentity.widgets import SelectMultipleWithPop + from .models import (TouristicContent, TouristicEvent, TouristicEventParticipantCount, - TouristicEventParticipantCategory) + TouristicEventParticipantCategory, TouristicEventOrganizer) from geotrek.common.forms import CommonForm @@ -142,6 +144,11 @@ def __init__(self, *args, **kwargs): self.fields['end_date'].widget.attrs['placeholder'] = _('dd/mm/yyyy') self.fields['start_time'].widget.attrs['placeholder'] = _('HH:MM') self.fields['end_time'].widget.attrs['placeholder'] = _('HH:MM') + if self.user.has_perm("tourism.add_touristiceventorganizer"): + self.fields['organizer'].widget = SelectMultipleWithPop( + choices=self.fields['organizer'].choices, + add_url=TouristicEventOrganizer.get_add_url() + ) # Since we use chosen() in trek_form.html, we don't need the default help text for f in ['themes', 'source']: self.fields[f].help_text = '' @@ -189,3 +196,9 @@ def _save_m2m(self): TouristicEventParticipantCount.objects.update_or_create(event=self.instance, category=category, defaults={'count': count}) else: TouristicEventParticipantCount.objects.filter(event=self.instance, category=category).delete() + + +class TouristicEventOrganizerFormPopup(CommonForm): + class Meta: + model = TouristicEventOrganizer + fields = ['label'] diff --git a/geotrek/tourism/models.py b/geotrek/tourism/models.py index 5b685ba716..5af120e49a 100644 --- a/geotrek/tourism/models.py +++ b/geotrek/tourism/models.py @@ -11,6 +11,7 @@ from django.dispatch import receiver from django.utils.formats import date_format from django.utils.translation import gettext_lazy as _ +from django.urls import reverse from easy_thumbnails.alias import aliases from easy_thumbnails.exceptions import InvalidImageFormatError from easy_thumbnails.files import get_thumbnailer @@ -397,6 +398,10 @@ class Meta: def __str__(self): return self.label + @classmethod + def get_add_url(cls): + return reverse('tourism:organizer_add') + class TouristicEvent(ZoningPropertiesMixin, AddPropertyMixin, PublishableMixin, GeotrekMapEntityMixin, StructureRelated, PicturesMixin, TimeStampedModelMixin, NoDeleteMixin): diff --git a/geotrek/tourism/templates/tourism/touristiceventorganizer_form.html b/geotrek/tourism/templates/tourism/touristiceventorganizer_form.html new file mode 100644 index 0000000000..7ce60b145f --- /dev/null +++ b/geotrek/tourism/templates/tourism/touristiceventorganizer_form.html @@ -0,0 +1,11 @@ +{% extends "mapentity/base_site.html" %} +{% load static i18n crispy_forms_tags %} + +{% block title %}{% trans "Add Organizer" %}{% endblock title %} + +{% block navbar %}{% endblock navbar %} + +{% block content %} +

{% trans "Add Organizer"%}

+{% crispy form %} +{% endblock content %} diff --git a/geotrek/tourism/urls.py b/geotrek/tourism/urls.py index 71400c9408..a47f71849a 100644 --- a/geotrek/tourism/urls.py +++ b/geotrek/tourism/urls.py @@ -22,6 +22,8 @@ path('api//touristiccategories.json', tourism_views.TouristicCategoryView.as_view(), name="touristic_categories_json"), path('api//touristiccontents//meta.html', tourism_views.TouristicContentMeta.as_view(), name="touristiccontent_meta"), path('api//touristicevents//meta.html', tourism_views.TouristicEventMeta.as_view(), name="touristicevent_meta"), + path('popup/add/organizer/', tourism_views.TouristicEventOrganizerCreatePopup.as_view(), name='organizer_add'), + ] diff --git a/geotrek/tourism/views.py b/geotrek/tourism/views.py index 9119e031df..f9fb011292 100644 --- a/geotrek/tourism/views.py +++ b/geotrek/tourism/views.py @@ -2,12 +2,16 @@ import os from django.conf import settings +from django.contrib.auth.decorators import login_required from django.contrib.gis.db.models.functions import Transform +from django.core.exceptions import PermissionDenied from django.db.models import Q, Sum -from django.http import Http404 +from django.http import Http404, HttpResponse from django.shortcuts import get_object_or_404 +from django.utils.decorators import method_decorator from django.utils.translation import gettext as _ -from django.views.generic import DetailView +from django.utils.html import escape +from django.views.generic import DetailView, CreateView from django_filters.rest_framework import DjangoFilterBackend from mapentity.views import (MapEntityCreate, MapEntityUpdate, MapEntityList, MapEntityDetail, MapEntityDelete, MapEntityFormat, MapEntityDocument) @@ -25,8 +29,8 @@ from geotrek.common.viewsets import GeotrekMapentityViewSet from geotrek.trekking.models import Trek from .filters import TouristicContentFilterSet, TouristicEventFilterSet, TouristicEventApiFilterSet -from .forms import TouristicContentForm, TouristicEventForm -from .models import (TouristicContent, TouristicEvent, TouristicContentCategory, InformationDesk) +from .forms import TouristicContentForm, TouristicEventForm, TouristicEventOrganizerFormPopup +from .models import (TouristicContent, TouristicEvent, TouristicContentCategory, TouristicEventOrganizer, InformationDesk) from .serializers import (TouristicContentSerializer, TouristicEventSerializer, TouristicContentAPIGeojsonSerializer, TouristicEventAPIGeojsonSerializer, InformationDeskGeojsonSerializer, TouristicContentAPISerializer, TouristicEventAPISerializer, @@ -275,6 +279,23 @@ def get_context_data(self, **kwargs): return context +class TouristicEventOrganizerCreatePopup(CreateView): + model = TouristicEventOrganizer + form_class = TouristicEventOrganizerFormPopup + + @method_decorator(login_required) + def dispatch(self, request, *args, **kwargs): + if not request.user.has_perm("tourism.add_touristiceventorganizer"): + raise PermissionDenied + return super().dispatch(request, *args, **kwargs) + + def form_valid(self, form): + self.object = form.save() + return HttpResponse(""" + + """ % (escape(form.instance._get_pk_val()), escape(form.instance))) + + class TouristicEventDocumentPublic(TouristicEventDocumentPublicMixin, DocumentPublic): pass