ソースを参照

create participant only when necessary

subDesTagesMitExtraKaese 2 年 前
コミット
84fb125994
5 ファイル変更62 行追加43 行削除
  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):
 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.'))
     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)
         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
 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. """
     """ Convert the slots of a participant to a string. """
+    if not participant:
+        return '0' * n_slots
 
 
     # Get the slots of the participant
     # Get the slots of the participant
     byte_array = participant.slots
     byte_array = participant.slots

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

@@ -1,8 +1,5 @@
 window.addEventListener("load", function()
 window.addEventListener("load", function()
 {
 {
-  const slotPicker = document.getElementsByClassName("slot-picker")[0]
-  const inputs = slotPicker.getElementsByTagName("input")
-
   const occupancyGrid = document.getElementsByClassName("occupancy-grid")[0]
   const occupancyGrid = document.getElementsByClassName("occupancy-grid")[0]
   const gridSlots = occupancyGrid.getElementsByClassName("slot")
   const gridSlots = occupancyGrid.getElementsByClassName("slot")
   
   
@@ -48,7 +45,10 @@ window.addEventListener("load", function()
       maxParticipants = Math.max(participants.length, maxParticipants)
       maxParticipants = Math.max(participants.length, maxParticipants)
     }
     }
     occupancyGrid.style.setProperty("--color-count", 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) {
   onCheckedChanged = function(checkables) {

+ 46 - 31
zitap/views.py

@@ -59,10 +59,9 @@ def create_event(request):
 @cache_page(60 * 15)
 @cache_page(60 * 15)
 @vary_on_cookie
 @vary_on_cookie
 def event(request, url):
 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')
         return render(request, 'zitap/event-not-found.html')
     
     
     # Check if the user is logged in
     # Check if the user is logged in
@@ -71,9 +70,10 @@ def event(request, url):
             if participant.user_id == request.session['user_id']:
             if participant.user_id == request.session['user_id']:
                 break
                 break
         else:
         else:
-            participant, created = Participant.objects.get_or_create(user_id=request.session['user_id'], event=event)
+            participant = None
         login_form = 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:
     else:
         login_form = LoginForm()
         login_form = LoginForm()
         update_form = None
         update_form = None
@@ -131,12 +131,18 @@ def update_slots(request, url):
     if request.method != 'POST':
     if request.method != 'POST':
         return HttpResponseNotAllowed(['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():
     if form.is_valid():
         data = form.cleaned_data
         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}')
         return HttpResponseRedirect(f'/{event.url}')
 
 
 def event_api(request, 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.
     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.
     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:
         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):
     def get_context(self, name, value, attrs):
         context = super().get_context(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
         return context
 
 
     def value_from_datadict(self, data, files, name):
     def value_from_datadict(self, data, files, name):
@@ -91,7 +92,8 @@ class SlotPickerWidget(Widget):
     def value_omitted_from_data(self, data, files, name):
     def value_omitted_from_data(self, data, files, name):
         return False
         return False
     
     
-    def __init__(self, *args, participant, **kwargs):
+    def __init__(self, *args, event, n_slots, participant, **kwargs):
         super().__init__(*args, **kwargs)
         super().__init__(*args, **kwargs)
+        self.event = event
         self.participant = participant
         self.participant = participant
-        self.n_slots = get_slot_count(participant.event)
+        self.n_slots = n_slots