import datetime from crispy_forms.helper import FormHelper from crispy_forms.layout import Submit from django.core.exceptions import PermissionDenied from django.forms import TextInput from django.forms.models import ModelForm from django.http import HttpResponse from django.shortcuts import redirect, render from django.views.generic.edit import CreateView, UpdateView from rest_framework import status from rest_framework.decorators import api_view from rest_framework.response import Response from location_field.widgets import LocationWidget from .models import Event, EventParticipation from .serializers import ParticipationSerializer # ---------------------------------------- API --------------------------------------------------------- @api_view(["GET", "PUT"]) def event_api(request, username=None, eventId=None): try: participationQs = EventParticipation.objects.filter( event__date__gte=datetime.date.today() ) if username: participationQs = EventParticipation.objects.filter(user__username=username) if eventId: participationQs = participationQs.filter(event__pk=eventId) except EventParticipation.DoesNotExist: return HttpResponse(status=404) if request.method == "GET": serializer = ParticipationSerializer(participationQs, many=True) return Response(serializer.data) elif request.method == "PUT": serializer = ParticipationSerializer(data=request.data, many=True) if serializer.is_valid(): for item in serializer.validated_data: event = item.get("event") user_obj = item.get("user") if not ( EventParticipation.isMember(request.user) or EventParticipation.isAdmin(request.user) ): return Response( {"error": "Permission denied - not a member"}, status=status.HTTP_403_FORBIDDEN, ) # Allow users to update their own participation # Admins can update anyone's participation if user_obj.pk != request.user.pk: if not EventParticipation.isAdmin(request.user): return Response( {"error": "Permission denied - can only update own status"}, status=status.HTTP_403_FORBIDDEN, ) instances = serializer.save() # Re-serialize the saved instances to return proper data response_serializer = ParticipationSerializer(instances, many=True) return Response(response_serializer.data) else: import logging logger = logging.getLogger(__name__) logger.error(f"API validation errors: {serializer.errors}") logger.error(f"Request data: {request.data}") return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) # ------------------------------------ Normal Views ---------------------------------------------------- def eventplanning(request): """ View for a specific user, to edit his events """ # non-members see the grid - but cannot edit anything if not EventParticipation.isMember(request.user): return events_grid(request) # All events in the future sorted by date all_future_events = list( Event.objects.filter(date__gte=datetime.date.today()).order_by("date") ) for e in all_future_events: e.participation = EventParticipation.get_or_create(event=e, user=request.user) context = {"events": all_future_events} return render(request, "eventplanner/eventplanning_view.html", context) def events_grid(request): usernames = [u.username for u in EventParticipation.members()] all_future_events = list( Event.objects.filter(date__gte=datetime.date.today()).order_by("date") ) for e in all_future_events: e.participation = [ EventParticipation.get_or_create(event=e, user=u) for u in EventParticipation.members() ] context = {"events": all_future_events, "usernames": usernames} return render(request, "eventplanner/events_grid.html", context) def deleteEvent(request, pk): if not EventParticipation.isAdmin(request.user): raise PermissionDenied Event.objects.get(pk=pk).delete() return redirect("eventplanner:events_grid") # ------------------------------------ Detail Views ---------------------------------------------------- class EventForm(ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_class = "form-horizontal" self.helper.add_input(Submit("submit", "Speichern")) class Meta: model = Event fields = [ "type", "short_desc", "date", "end_date", "time", "meeting_time", "location", "map_location", "desc", ] widgets = { "location": TextInput(), "map_location": LocationWidget(), } class EventUpdate(UpdateView): form_class = EventForm model = Event template_name_suffix = "_update_form" success_url = "." def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["viewtype"] = "update" return context class EventCreate(CreateView): form_class = EventForm model = Event template_name_suffix = "_update_form" success_url = "." def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["viewtype"] = "create" return context