Procházet zdrojové kódy

finish update loop

subDesTagesMitExtraKaese před 2 roky
rodič
revize
b454e05353

+ 2 - 2
locale/de/LC_MESSAGES/django.po

@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-12-18 01:25+0000\n"
+"POT-Creation-Date: 2022-12-18 13:06+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -28,7 +28,7 @@ msgstr ""
 msgid "Event not found"
 msgid "Event not found"
 msgstr ""
 msgstr ""
 
 
-#: zitap/templates/zitap/event.html:45
+#: zitap/templates/zitap/event.html:38
 msgid "Logout"
 msgid "Logout"
 msgstr ""
 msgstr ""
 
 

+ 7 - 2
zitap/helpers.py

@@ -28,7 +28,9 @@ def get_slot_count( event ) -> int :
     # Get the timespan of the event
     # Get the timespan of the event
     start_time = datetime.datetime.combine(datetime.date.today(), event.start_time)
     start_time = datetime.datetime.combine(datetime.date.today(), event.start_time)
     end_time = datetime.datetime.combine(datetime.date.today(), event.end_time)
     end_time = datetime.datetime.combine(datetime.date.today(), event.end_time)
-    timespan = abs(end_time - start_time)
+    if(start_time>end_time):
+        end_time += datetime.timedelta(days=1)
+    timespan = end_time - start_time
 
 
     # Get the number of slots in the event
     # Get the number of slots in the event
     days = event.date_set.count()
     days = event.date_set.count()
@@ -50,7 +52,9 @@ def slots2grid( event : Event, participants : list[Participant]) -> dict :
     # Get the timespan of the event
     # Get the timespan of the event
     start_time = datetime.datetime.combine(datetime.date.today(), event.start_time)
     start_time = datetime.datetime.combine(datetime.date.today(), event.start_time)
     end_time = datetime.datetime.combine(datetime.date.today(), event.end_time)
     end_time = datetime.datetime.combine(datetime.date.today(), event.end_time)
-    timespan = abs(end_time - start_time)
+    if(start_time>end_time):
+        end_time += datetime.timedelta(days=1)
+    timespan = end_time - start_time
     
     
     # Get the slots in a day
     # Get the slots in a day
     slots_per_day = int(timespan.total_seconds() // event.slot_interval.total_seconds())
     slots_per_day = int(timespan.total_seconds() // event.slot_interval.total_seconds())
@@ -80,6 +84,7 @@ def slots2grid( event : Event, participants : list[Participant]) -> dict :
                 'date': date.date,
                 'date': date.date,
                 'time': current_time,
                 'time': current_time,
                 'color': len(ps),
                 'color': len(ps),
+                'checked': 'checked="checked"' if len(ps) > 0 else '',
                 'is_full_hour': current_time.hour != last_hour,
                 'is_full_hour': current_time.hour != last_hour,
                 'is_half_hour': current_time.minute // 30 != last_half_hour,
                 'is_half_hour': current_time.minute // 30 != last_half_hour,
             })
             })

+ 2 - 1
zitap/static/zitap/css/event.css

@@ -34,7 +34,7 @@
   z-index: 1;
   z-index: 1;
 }
 }
 .occupancy-grid .slot {
 .occupancy-grid .slot {
-  transition: background-color .2s ease;
+  transition: background-color 1s ease;
   position: relative;
   position: relative;
   width: var(--slot-witdh);
   width: var(--slot-witdh);
   flex-grow: 1;
   flex-grow: 1;
@@ -61,5 +61,6 @@
 }
 }
 .occupancy-grid .slot:hover {
 .occupancy-grid .slot:hover {
   background-color: rgb(214, 93, 93) !important;
   background-color: rgb(214, 93, 93) !important;
+  transition: background-color 0.2s ease !important;
   cursor: pointer;
   cursor: pointer;
 }
 }

+ 32 - 15
zitap/static/zitap/js/live-updates.js

@@ -12,22 +12,39 @@ window.addEventListener("load", function()
   function updateSlots()
   function updateSlots()
   {
   {
     setTimeout(updateSlots, 5000)
     setTimeout(updateSlots, 5000)
-    fetch(endpoint).then(response => response.json()).then(data => {
-      let maxParticipants = 0
-      for(let i=0; i<gridSlots.length; i++)
+    fetch(endpoint).then(response => response.json()).then(setCheckboxes)
+  }
+
+  function setCheckboxes(data)
+  {
+    let maxParticipants = 0
+    for(let i=0; i<gridSlots.length; i++)
+    {
+      const slot = document.getElementById(`grid_slot_${i}`)
+      let participants = []
+      for(let participant in data)
       {
       {
-        const slot = document.getElementById(`grid_slot_${i}`)
-        let participants = []
-        for(let participant in data)
-        {
-          if(data[participant][i] == '1')
-            participants.push(participant)
-        }
-        slot.style.setProperty("--color-index", participants.length)
-        slot.title = `${slot.title.split('\n')[0]}\n${participants.join(", ")}`
-        maxParticipants = Math.max(participants.length, maxParticipants)
+        if(data[participant][i] == '1')
+          participants.push(participant)
       }
       }
-      occupancyGrid.style.setProperty("--color-count", maxParticipants)
-    })
+      slot.style.setProperty("--color-index", participants.length)
+      slot.title = `${slot.title.split('\n')[0]}\n${participants.join(", ")}`
+      maxParticipants = Math.max(participants.length, maxParticipants)
+    }
+    occupancyGrid.style.setProperty("--color-count", maxParticipants)
   }
   }
+
+  onCheckedChanged = function(checkables) {
+    const data = new URLSearchParams();
+    for (const pair of new FormData(document.getElementById("update-form"))) {
+        data.append(pair[0], pair[1]);
+    }
+
+    fetch(endpoint, {
+        method: 'post',
+        body: data,
+    }).then(response => response.json()).then(setCheckboxes)
+  }
+
+  this.document.getElementById("update-button").style.display = "none"
 })
 })

+ 6 - 0
zitap/static/zitap/js/mouse-drag.js

@@ -1,3 +1,5 @@
+let onCheckedChanged = null
+
 window.addEventListener("load", function()
 window.addEventListener("load", function()
 {
 {
   let dragStart = null
   let dragStart = null
@@ -44,6 +46,10 @@ window.addEventListener("load", function()
     let rectElement = document.getElementById("rect")
     let rectElement = document.getElementById("rect")
     if (rectElement)
     if (rectElement)
       rectElement.parentNode.removeChild(rectElement)
       rectElement.parentNode.removeChild(rectElement)
+
+    if(onCheckedChanged) {
+      onCheckedChanged(checkables)
+    }
   }
   }
   function mouseMoveHandler(e)
   function mouseMoveHandler(e)
   {
   {

+ 1 - 1
zitap/templates/widgets/slot-picker.html

@@ -5,7 +5,7 @@
       {% for slot in day.slots %}
       {% for slot in day.slots %}
       <div class="slot {% if slot.is_full_hour %} full-hour{% elif slot.is_half_hour %} half-hour{% endif %}" title="{{ slot.tooltip }}">
       <div class="slot {% if slot.is_full_hour %} full-hour{% elif slot.is_half_hour %} half-hour{% endif %}" title="{{ slot.tooltip }}">
           {% if slot.is_full_hour %}<div class="time-label">{{ slot.time|date:"H:i" }}</div>{% endif %}
           {% if slot.is_full_hour %}<div class="time-label">{{ slot.time|date:"H:i" }}</div>{% endif %}
-          <input class="checkable" type="checkbox" id="slot_picker_{{ slot.offset }}" name="slot_{{ slot.offset }}" />
+          <input class="checkable" type="checkbox" id="slot_picker_{{ slot.offset }}" name="slot_{{ slot.offset }}" {{ slot.checked }} />
           <label class="checkable" for="slot_picker_{{ slot.offset }}"></label>
           <label class="checkable" for="slot_picker_{{ slot.offset }}"></label>
       </div>
       </div>
       {% endfor %}
       {% endfor %}

+ 4 - 4
zitap/templates/zitap/event.html

@@ -27,24 +27,24 @@
 
 
 
 
 {% if update_form %}
 {% if update_form %}
-    <form action="{% url 'update-slots' url=event.url %}" method="post">
+    <form action="{% url 'update-slots' url=event.url %}" method="post" id="update-form">
         {% csrf_token %}
         {% csrf_token %}
         <table>
         <table>
             {{ update_form.as_table }}
             {{ update_form.as_table }}
         </table>
         </table>
-        <input type="submit" value="Update Slots">
+        <input type="submit" value="Update Slots" id="update-button">
     </form>
     </form>
     <button class="logout" onclick="location.href='{% url 'logout' url=event.url %}'">
     <button class="logout" onclick="location.href='{% url 'logout' url=event.url %}'">
         {% trans "Logout" %}
         {% trans "Logout" %}
     </button>
     </button>
     <script type="text/javascript" src="{% static 'zitap/js/mouse-drag.js' %}"></script>
     <script type="text/javascript" src="{% static 'zitap/js/mouse-drag.js' %}"></script>
     {% else %}
     {% else %}
-    <form action="{% url 'login' url=event.url %}" method="post">
+    <form action="{% url 'login' url=event.url %}" method="post" id="login-form">
         {% csrf_token %}
         {% csrf_token %}
         <table>
         <table>
             {{ login_form.as_table }}
             {{ login_form.as_table }}
         </table>
         </table>
-        <input type="submit" value="Login to Update Slots">
+        <input type="submit" value="Login to Update Slots" id="login-button">
     </form>
     </form>
     {% endif %}
     {% endif %}
     <script type="text/javascript" src="{% static 'zitap/js/live-updates.js' %}"></script>
     <script type="text/javascript" src="{% static 'zitap/js/live-updates.js' %}"></script>

+ 3 - 3
zitap/views.py

@@ -1,9 +1,9 @@
-import random
 import datetime
 import datetime
 from django.db import IntegrityError
 from django.db import IntegrityError
 from django.http import HttpResponseNotFound, HttpResponseRedirect, JsonResponse, HttpResponseNotAllowed
 from django.http import HttpResponseNotFound, HttpResponseRedirect, JsonResponse, HttpResponseNotAllowed
 from django.shortcuts import render
 from django.shortcuts import render
 from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
 from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
+from django.views.decorators.csrf import csrf_exempt
 from django.contrib.auth.models import User
 from django.contrib.auth.models import User
 
 
 from .forms import CreateEventForm, LoginForm, UpdateSlotsForm
 from .forms import CreateEventForm, LoginForm, UpdateSlotsForm
@@ -88,7 +88,6 @@ def login(request, url):
 
 
         auth_login(request, user)
         auth_login(request, user)
         participant, created = Participant.objects.get_or_create(event=event, user=user)
         participant, created = Participant.objects.get_or_create(event=event, user=user)
-        participant.slots = random.getrandbits(get_slot_count(event)).to_bytes((get_slot_count(event)+7) // 8, 'big')
         participant.save()
         participant.save()
         request.session['user_id'] = user.id
         request.session['user_id'] = user.id
         return HttpResponseRedirect(f'/{event.url}')
         return HttpResponseRedirect(f'/{event.url}')
@@ -120,6 +119,7 @@ def update_slots(request, url):
         participant.save()
         participant.save()
         return HttpResponseRedirect(f'/{event.url}')
         return HttpResponseRedirect(f'/{event.url}')
 
 
+@csrf_exempt
 def slots_api(request, url):
 def slots_api(request, url):
     """
     """
     REST JSON API for slots of all participants of an event
     REST JSON API for slots of all participants of an event
@@ -136,6 +136,7 @@ def slots_api(request, url):
             form = UpdateSlotsForm(request.POST, participant=participant)
             form = UpdateSlotsForm(request.POST, participant=participant)
             if form.is_valid():
             if form.is_valid():
                 data = form.cleaned_data
                 data = form.cleaned_data
+                print(data['slots'])
                 participant.slots = string2slots(data['slots'], slot_count)
                 participant.slots = string2slots(data['slots'], slot_count)
                 participant.save()
                 participant.save()
 
 
@@ -144,7 +145,6 @@ def slots_api(request, url):
         participants = event.participant_set.all()
         participants = event.participant_set.all()
         for participant in participants:
         for participant in participants:
             data[participant.user.username] = slots2string(participant, slot_count)
             data[participant.user.username] = slots2string(participant, slot_count)
-            data[participant.user.username] = ''.join([random.choice(('0', '1')) for _ in range(slot_count)])
         
         
         return JsonResponse(data)
         return JsonResponse(data)
 
 

+ 10 - 7
zitap/widgets.py

@@ -1,4 +1,5 @@
 import datetime
 import datetime
+import ctypes
 
 
 from django.forms.widgets import Widget
 from django.forms.widgets import Widget
 from .models import Participant, Date, Event
 from .models import Participant, Date, Event
@@ -75,17 +76,19 @@ class SlotPickerWidget(Widget):
         return context
         return context
 
 
     def value_from_datadict(self, data, files, name):
     def value_from_datadict(self, data, files, name):
-        slots = []
+        # create a mutable string buffer
+        slots = ctypes.create_string_buffer(self.n_slots)
+        # set the slots
         for i in range(self.n_slots):
         for i in range(self.n_slots):
             if data.get(f"slot_{i}") == "on":
             if data.get(f"slot_{i}") == "on":
-                slots.append(i)
-        return slots
+                slots[i] = b'1'
+            else:
+                slots[i] = b'0'
+        # return the slots as a string
+        return slots.value
 
 
     def value_omitted_from_data(self, data, files, name):
     def value_omitted_from_data(self, data, files, name):
-        return not any(
-            (data.get(f"slot_{i}") == "on")
-            for i in range(self.n_slots)
-        )
+        return False
     
     
     def __init__(self, *args, participant, **kwargs):
     def __init__(self, *args, participant, **kwargs):
         super().__init__(*args, **kwargs)
         super().__init__(*args, **kwargs)