Browse Source

create participant only when necessary

subDesTagesMitExtraKaese 2 years ago
parent
commit
84fb125994
5 changed files with 62 additions and 43 deletions
  1. 2 2
      zitap/forms.py
  2. 3 1
      zitap/helpers.py
  3. 4 4
      zitap/static/zitap/js/live-updates.js
  4. 46 31
      zitap/views.py
  5. 7 5
      zitap/widgets.py

+ 2 - 2
zitap/forms.py

@@ -34,6 +34,6 @@ class LoginForm(forms.Form):
 class UpdateSlotsForm(forms.Form):
     slots = forms.Field(label=_('Slots'), help_text=_('Click on a time slot to select it. Click again to deselect it. You can also drag the mouse to select multiple slots.'))
 
-    def __init__(self, *args, participant, **kwargs):
+    def __init__(self, *args, event, n_slots, participant, **kwargs):
         super().__init__(*args, **kwargs)
-        self.fields['slots'].widget = SlotPickerWidget(participant=participant)
+        self.fields['slots'].widget = SlotPickerWidget(event=event, n_slots=n_slots, participant=participant)

+ 3 - 1
zitap/helpers.py

@@ -4,8 +4,10 @@ from django.utils.html import escape
 
 from .models import Participant, Date, Event
 
-def slots2string( participant : Participant, n_slots : int ) -> str :
+def slots2string( participant : Participant | None, n_slots : int ) -> str :
     """ Convert the slots of a participant to a string. """
+    if not participant:
+        return '0' * n_slots
 
     # Get the slots of the participant
     byte_array = participant.slots

+ 4 - 4
zitap/static/zitap/js/live-updates.js

@@ -1,8 +1,5 @@
 window.addEventListener("load", function()
 {
-  const slotPicker = document.getElementsByClassName("slot-picker")[0]
-  const inputs = slotPicker.getElementsByTagName("input")
-
   const occupancyGrid = document.getElementsByClassName("occupancy-grid")[0]
   const gridSlots = occupancyGrid.getElementsByClassName("slot")
   
@@ -48,7 +45,10 @@ window.addEventListener("load", function()
       maxParticipants = Math.max(participants.length, maxParticipants)
     }
     occupancyGrid.style.setProperty("--color-count", maxParticipants)
-    this.document.getElementById("update-button").style.display = "none"
+    
+    const updateButton = this.document.getElementById("update-button")
+    if(updateButton)
+      updateButton.style.display = "none"
   }
 
   onCheckedChanged = function(checkables) {

+ 46 - 31
zitap/views.py

@@ -59,10 +59,9 @@ def create_event(request):
 @cache_page(60 * 15)
 @vary_on_cookie
 def event(request, url):
-    try:
-        participants = list(Participant.objects.prefetch_related('user', 'event', 'event__date_set').filter(event__url=url))
-        event = participants[0].event
-    except Event.DoesNotExist:
+    event = Event.objects.filter(url=url).prefetch_related('date_set', 'participant_set', 'participant_set__user').first()
+    participants = list(event.participant_set.all()) if event else []
+    if not event:
         return render(request, 'zitap/event-not-found.html')
     
     # Check if the user is logged in
@@ -71,9 +70,10 @@ def event(request, url):
             if participant.user_id == request.session['user_id']:
                 break
         else:
-            participant, created = Participant.objects.get_or_create(user_id=request.session['user_id'], event=event)
+            participant = None
         login_form = None
-        update_form = UpdateSlotsForm(initial={'slots': slots2string(participant, get_slot_count(event))}, participant=participant)
+        n_slots = get_slot_count(event)
+        update_form = UpdateSlotsForm(initial={'slots': slots2string(participant, n_slots)}, event=event, n_slots=n_slots, participant=participant)
     else:
         login_form = LoginForm()
         update_form = None
@@ -131,12 +131,18 @@ def update_slots(request, url):
     if request.method != 'POST':
         return HttpResponseNotAllowed(['POST'])
 
-    participant = Participant.objects.get(user_id=request.session['user_id'], event=event)
-    form = UpdateSlotsForm(request.POST, participant=participant)
+    slot_count = get_slot_count(event)
+    participant = event.participant_set.filter(user_id=request.session['user_id'], event=event).first()
+    form = UpdateSlotsForm(request.POST, event=event, n_slots=slot_count, participant=participant)
     if form.is_valid():
         data = form.cleaned_data
-        participant.slots = string2slots(data['slots'], get_slot_count(event))
-        participant.save()
+        if data['slots'] == '0' * slot_count and participant:
+            participant.delete()
+        elif not participant:
+            participant = Participant.objects.create(user_id=request.session['user_id'], event=event, slots=string2slots(data['slots'], slot_count))
+        else:
+            participant.slots = string2slots(data['slots'], slot_count)
+            participant.save()
         return HttpResponseRedirect(f'/{event.url}')
 
 def event_api(request, url):
@@ -166,28 +172,37 @@ def slots_api(request, url):
     Slots are represented as a string of 0s and 1s where 0 means the slot is available and 1 means the slot is taken.
     The string begins with the first slot of the first day of the event and ends with the last slot of the last day of the event.
     """
-    try:
-        participants = Participant.objects.select_related('event', 'user').filter(event__url=url)
-        event = participants.first().event
-        slot_count = get_slot_count(event)
+    event = Event.objects.filter(url=url).prefetch_related('date_set', 'participant_set', 'participant_set__user').first()
+    participants = list(event.participant_set.all()) if event else []
+    if not event:
+        return HttpResponseNotFound()
 
-        # Check if the user is logged in and wants to update their slots
-        if 'user_id' in request.session and request.method == 'POST':
-            participant = participants.filter(user_id=request.session['user_id']).first()
-            if participant is None:
-                participant = Participant.objects.get_or_create(user_id=request.session['user_id'], event=event)
-            form = UpdateSlotsForm(request.POST, participant=participant)
-            if form.is_valid():
-                data = form.cleaned_data
-                participant.slots = string2slots(data['slots'], slot_count)
-                participant.save()
+    slot_count = get_slot_count(event)
 
-        # Get the slots of each participant
-        data = {}
+    # Check if the user is logged in and wants to update their slots
+    if 'user_id' in request.session and request.method == 'POST':
         for participant in participants:
-            data[participant.user.username] = slots2string(participant, slot_count)
-        
-        return JsonResponse(data)
+            if participant.user_id == request.session['user_id']:
+                break
+        else:
+            participant = None
+            
+        slot_count = get_slot_count(event)
+        form = UpdateSlotsForm(request.POST, event=event, n_slots=slot_count, participant=participant)
+        if form.is_valid():
+            data = form.cleaned_data
+            if data['slots'] == '0' * slot_count and participant:
+                participant.delete()
+            elif not participant:
+                participant = Participant.objects.create(user_id=request.session['user_id'], event=event, slots=string2slots(data['slots'], slot_count))
+            else:
+                participant.slots = string2slots(data['slots'], slot_count)
+                participant.save()
 
-    except Event.DoesNotExist:
-        return HttpResponseNotFound()
+    # Get the slots of each participant
+    data = {}
+    for participant in participants:
+        data[participant.user.username] = slots2string(participant, slot_count)
+    
+    return JsonResponse(data)
+        

+ 7 - 5
zitap/widgets.py

@@ -71,9 +71,10 @@ class SlotPickerWidget(Widget):
 
     def get_context(self, name, value, attrs):
         context = super().get_context(name, value, attrs)
-        event: Event = self.participant.event
-
-        context['widget']['grid'] = slots2grid(event, [self.participant], True)
+        if self.participant:
+            context['widget']['grid'] = slots2grid(self.event, [self.participant], True)
+        else:
+            context['widget']['grid'] = slots2grid(self.event, [], True)
         return context
 
     def value_from_datadict(self, data, files, name):
@@ -91,7 +92,8 @@ class SlotPickerWidget(Widget):
     def value_omitted_from_data(self, data, files, name):
         return False
     
-    def __init__(self, *args, participant, **kwargs):
+    def __init__(self, *args, event, n_slots, participant, **kwargs):
         super().__init__(*args, **kwargs)
+        self.event = event
         self.participant = participant
-        self.n_slots = get_slot_count(participant.event)
+        self.n_slots = n_slots