Sfoglia il codice sorgente

optimize templates

subDesTagesMitExtraKaese 2 anni fa
parent
commit
9313fedfd0

+ 14 - 10
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 23:10+0000\n"
+"POT-Creation-Date: 2022-12-21 18:02+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"
@@ -73,7 +73,9 @@ msgstr "Passwort"
 #: zitap/forms.py:32
 #: zitap/forms.py:32
 msgid ""
 msgid ""
 "Fill in a password to create a new account. Leave empty to login as a guest."
 "Fill in a password to create a new account. Leave empty to login as a guest."
-msgstr "Füllen Sie ein Passwort ein, um ein neues Konto zu erstellen. Leer lassen, um als Gast einzuloggen."
+msgstr ""
+"Füllen Sie ein Passwort ein, um ein neues Konto zu erstellen. Leer lassen, "
+"um als Gast einzuloggen."
 
 
 #: zitap/forms.py:35
 #: zitap/forms.py:35
 msgid "Slots"
 msgid "Slots"
@@ -83,9 +85,11 @@ msgstr "Zeitslots"
 msgid ""
 msgid ""
 "Click on a time slot to select it. Click again to deselect it. You can also "
 "Click on a time slot to select it. Click again to deselect it. You can also "
 "drag the mouse to select multiple slots."
 "drag the mouse to select multiple slots."
-msgstr "Ziehe die Maus über einen Zeitslot, um ihn auszuwählen. Markiere ihn erneut, um ihn abzuwählen."
+msgstr ""
+"Ziehe die Maus über einen Zeitslot, um ihn auszuwählen. Markiere ihn erneut, "
+"um ihn abzuwählen."
 
 
-#: zitap/helpers.py:21
+#: zitap/helpers.py:22
 #, fuzzy, python-brace-format
 #, fuzzy, python-brace-format
 #| msgid "Invalid string length"
 #| msgid "Invalid string length"
 msgid "Invalid string length: {0} (expected: {1})"
 msgid "Invalid string length: {0} (expected: {1})"
@@ -117,15 +121,15 @@ msgstr "Ereignis nicht gefunden"
 msgid "Event"
 msgid "Event"
 msgstr "Ereignis"
 msgstr "Ereignis"
 
 
-#: zitap/templates/zitap/event.html:49
+#: zitap/templates/zitap/event.html:37
 msgid "Update Slots"
 msgid "Update Slots"
 msgstr "Zeitslot aktualisieren"
 msgstr "Zeitslot aktualisieren"
 
 
-#: zitap/templates/zitap/event.html:52 zitap/templates/zitap/my-events.html:32
+#: zitap/templates/zitap/event.html:40 zitap/templates/zitap/my-events.html:32
 msgid "Logout"
 msgid "Logout"
 msgstr "Abmelden"
 msgstr "Abmelden"
 
 
-#: zitap/templates/zitap/event.html:75 zitap/views.py:78
+#: zitap/templates/zitap/event.html:63 zitap/views.py:79
 msgid "Login to Update Slots"
 msgid "Login to Update Slots"
 msgstr "Anmelden, um Zeitslots zu aktualisieren"
 msgstr "Anmelden, um Zeitslots zu aktualisieren"
 
 
@@ -144,16 +148,16 @@ msgstr "Meine Ereignisse"
 msgid "Login"
 msgid "Login"
 msgstr "Anmelden"
 msgstr "Anmelden"
 
 
-#: zitap/views.py:49
+#: zitap/views.py:50
 msgid "Could not create event. Please try again."
 msgid "Could not create event. Please try again."
 msgstr "Konnte Ereignis nicht erstellen. Bitte versuchen Sie es erneut."
 msgstr "Konnte Ereignis nicht erstellen. Bitte versuchen Sie es erneut."
 
 
-#: zitap/views.py:76
+#: zitap/views.py:77
 #, fuzzy
 #, fuzzy
 #| msgid "Event"
 #| msgid "Event"
 msgid "Login to My Events"
 msgid "Login to My Events"
 msgstr "Anmelden, um meine Ereignisse anzuzeigen"
 msgstr "Anmelden, um meine Ereignisse anzuzeigen"
 
 
-#: zitap/views.py:95
+#: zitap/views.py:96
 msgid "Username already exists"
 msgid "Username already exists"
 msgstr "Benutzername existiert bereits"
 msgstr "Benutzername existiert bereits"

+ 70 - 62
zitap/helpers.py

@@ -1,5 +1,6 @@
 import datetime
 import datetime
 from django.utils.translation import gettext as _
 from django.utils.translation import gettext as _
+from django.utils.html import escape
 
 
 from .models import Participant, Date, Event
 from .models import Participant, Date, Event
 
 
@@ -38,18 +39,10 @@ def get_slot_count( event ) -> int :
     slots_per_day = int(timespan.total_seconds() // event.slot_interval.total_seconds())
     slots_per_day = int(timespan.total_seconds() // event.slot_interval.total_seconds())
     return days * slots_per_day
     return days * slots_per_day
 
 
-def slots2grid( event : Event, participants : list[Participant]) -> dict :
+def slots2grid( event : Event, participants : list[Participant], is_input : bool) -> dict :
     """ Convert the slots of an event to data for the grid. """
     """ Convert the slots of an event to data for the grid. """
-
     # Get the number of slots in the event
     # Get the number of slots in the event
     n_slots = get_slot_count(event)
     n_slots = get_slot_count(event)
-
-    data = {
-        'rows': [],
-        'days': [],
-        'colors': [],
-        'n_days': event.date_set.count(),
-    }
     # 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)
@@ -62,57 +55,72 @@ def slots2grid( event : Event, participants : list[Participant]) -> dict :
 
 
     # Get the slots of each day
     # Get the slots of each day
     participant_slot_strings = [slots2string(participant, n_slots) for participant in participants]
     participant_slot_strings = [slots2string(participant, n_slots) for participant in participants]
-    max_occupancy = 1
-
-    for n, date in enumerate(event.date_set.all()):
-        # Get participants for each slot
-        slot_participants = [[] for i in range(slots_per_day)]
-        for i, participant in enumerate(participants):
+    if is_input:
+        html = []
+        for n, date in reversed(list(enumerate(event.date_set.all()))):
+            day_offset = n * slots_per_day
+            dt = datetime.datetime.combine(date.date, datetime.time())
+            html += f'<div class="slot-column"><div class="day">{ dt.strftime("%b %d") }</div>'
+            slots = []
+
+            # Fill the slots of the day
+            for j in range(slots_per_day):
+                slot_begin = (start_time + j * event.slot_interval).strftime('%H:%M')
+                slot_end = (start_time + (j+1) * event.slot_interval).strftime('%H:%M')
+                current_time = start_time + j * event.slot_interval
+                if current_time.minute == 0:
+                    time_label = f'<div class=\"time-label\">{current_time.strftime("%H:%M")}</div>'
+                    classes = " full-hour"
+                elif current_time.minute == 30:
+                    time_label = ""
+                    classes = " half-hour"
+                else:
+                    time_label = ""
+                    classes = ""
+                checked = ""
+                for i in range(len(participant_slot_strings)):
+                    if participant_slot_strings[i][day_offset + j] == '1':
+                        checked = 'checked'
+                        break
+
+                slots.append(
+                    f'<div class="slot{classes}" title="{slot_begin} - {slot_end}">{ time_label }<input class="checkable" type="checkbox" id="slot_picker_{ day_offset + j }" name="slot_{day_offset + j}" { checked } /><label class="checkable" for="slot_picker_{day_offset + j}"></label></div>')
+            html.append(''.join(slots))
+            html.append('</div>')
+        return "".join(html)
+    else:
+        max_occupancy = 1
+        html = []
+        for n, date in reversed(list(enumerate(event.date_set.all()))):
+            day_offset = n * slots_per_day
+            dt = datetime.datetime.combine(date.date, datetime.time())
+            html.append(f'<div class="slot-column"><div class="day">{ dt.strftime("%b %d") }</div>')
+            slots = []
+            # Get participants for each slot
+            slot_participants = [[] for i in range(slots_per_day)]
             for j in range(slots_per_day):
             for j in range(slots_per_day):
-                if participant_slot_strings[i][n*slots_per_day + j] == '1':
-                    slot_participants[j].append(participant)
-        # Fill the slots of the day
-        slots = []
-        last_hour = None
-        last_half_hour = None
-        for j, ps in enumerate(slot_participants):
-            slot_begin = (start_time + j * event.slot_interval).strftime('%H:%M')
-            slot_end = (start_time + (j+1) * event.slot_interval).strftime('%H:%M')
-            current_time = start_time + j * event.slot_interval
-            slots.append({
-                'tooltip': f"{slot_begin} - {slot_end} \n{', '.join([p.user.username for p in ps])}",
-                'offset': n*slots_per_day + j,
-                'date': date.date,
-                'time': current_time,
-                'color': len(ps),
-                'checked': 'checked="checked"' if len(ps) > 0 else '',
-                'is_full_hour': current_time.hour != last_hour,
-                'is_half_hour': current_time.minute // 30 != last_half_hour,
-            })
-            max_occupancy = max(max_occupancy, len(ps))
-            last_hour = current_time.hour
-            last_half_hour = current_time.minute // 30
-        
-        day = {
-            'date': date.date,
-            'slots': slots,
-        }
-        data['days'].append(day)
-    data['days'] = reversed(data['days'])
-    # Fill the rows of the grid
-    last_hour = None
-    for i in range(slots_per_day):
-        current_time = start_time + i * event.slot_interval
-        data['rows'].append({
-            'time': current_time,
-            'is_full_hour': current_time.hour != last_hour,
-        })
-        last_hour = current_time.hour
-
-    data['rows'].append({
-        'time': end_time,
-        'is_full_hour': True,
-    })
-
-    data['colors'] = max_occupancy
-    return data
+                for i in range(len(participant_slot_strings)):
+                    if participant_slot_strings[i][day_offset + j] == '1':
+                        slot_participants[j].append(i)
+
+            # Fill the slots of the day
+            for j, ps in enumerate(slot_participants):
+                slot_begin = (start_time + j * event.slot_interval).strftime('%H:%M')
+                slot_end = (start_time + (j+1) * event.slot_interval).strftime('%H:%M')
+                current_time = start_time + j * event.slot_interval
+                if current_time.minute == 0:
+                    time_label = f'<div class=\"time-label\">{current_time.strftime("%H:%M")}</div>'
+                    classes = " full-hour"
+                elif current_time.minute == 30:
+                    time_label = ""
+                    classes = " half-hour"
+                else:
+                    time_label = ""
+                    classes = ""
+
+                slots.append(
+                    f'<div class="slot{classes}" id="grid_slot_{ day_offset + j }" title="{slot_begin} - {slot_end} \n{escape(", ".join([participants[p].user.username for p in ps]))}" style="--color-index:{ len(ps) }">{ time_label }</div>')
+                max_occupancy = max(max_occupancy, len(ps))
+            html.append(''.join(slots))
+            html.append('</div>')
+        return f'<div class="occupancy-grid" style="--color-count:{ max_occupancy }">{"".join(html)}</div>'

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

@@ -1,14 +1,3 @@
 <div class="slot-picker" id="{{ widget.attrs.id }}">
 <div class="slot-picker" id="{{ widget.attrs.id }}">
-  {% for day in widget.grid.days %}
-  <div class="slot-column">
-      <div class="day">{{ day.date|date:"M d" }}</div>
-      {% 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 }}">
-          {% 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 }}" {{ slot.checked }} />
-          <label class="checkable" for="slot_picker_{{ slot.offset }}"></label>
-      </div>
-      {% endfor %}
-  </div>
-  {% endfor %}
+  {{ widget.grid | safe}}
 </div>
 </div>

+ 1 - 13
zitap/templates/zitap/event.html

@@ -12,19 +12,7 @@
 {% block content %}
 {% block content %}
 <h1>{% trans "Event" %}: {{ event.name }}</h1>
 <h1>{% trans "Event" %}: {{ event.name }}</h1>
 
 
-<div class="occupancy-grid" style="--color-count:{{ grid.colors }}">
-    {% for day in grid.days %}
-    <div class="slot-column">
-        <div class="day">{{ day.date|date:"M d" }}</div>
-        {% for slot in day.slots %}
-        <div class="slot{% if slot.is_full_hour %} full-hour{% elif slot.is_half_hour %} half-hour{% endif %}" id="grid_slot_{{ slot.offset }}" title="{{ slot.tooltip }}" style="--color-index:{{ slot.color }}">
-            {% if slot.is_full_hour %}<div class="time-label">{{ slot.time|date:"H:i" }}</div>{% endif %}
-        </div>
-        {% endfor %}
-    </div>
-    {% endfor %}
-</div>
-
+{{ grid | safe }}
 
 
 {% if update_form %}
 {% if update_form %}
     <form action="{% url 'update-slots' url=event.url %}" method="post" id="update-form">
     <form action="{% url 'update-slots' url=event.url %}" method="post" id="update-form">

+ 5 - 3
zitap/views.py

@@ -54,13 +54,15 @@ def create_event(request):
 
 
 def event(request, url):
 def event(request, url):
     try:
     try:
-        event = Event.objects.get(url=url)
+        event = Event.objects.prefetch_related('date_set', 'participant_set', 'participant_set__user').get(url=url)
     except Event.DoesNotExist:
     except Event.DoesNotExist:
         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
     if 'user_id' in request.session:
     if 'user_id' in request.session:
-        participant, created = Participant.objects.get_or_create(user_id=request.session['user_id'], event=event)
+        participant = event.participant_set.filter(user_id=request.session['user_id']).first()
+        if participant is None:
+            participant, created = Participant.objects.get_or_create(user_id=request.session['user_id'], event=event)
         login_form = None
         login_form = None
         update_form = UpdateSlotsForm(initial={'slots': slots2string(participant, get_slot_count(event))}, participant=participant)
         update_form = UpdateSlotsForm(initial={'slots': slots2string(participant, get_slot_count(event))}, participant=participant)
     else:
     else:
@@ -69,7 +71,7 @@ def event(request, url):
     return render(
     return render(
         request, 
         request, 
         'zitap/event.html', 
         'zitap/event.html', 
-        {'event': event, 'grid': slots2grid(event, event.participant_set.all()), 'login_form': login_form, 'update_form': update_form}
+        {'event': event, 'grid': slots2grid(event, list(event.participant_set.all()), False), 'login_form': login_form, 'update_form': update_form}
     )
     )
 
 
 def login(request, url):
 def login(request, url):

+ 1 - 1
zitap/widgets.py

@@ -73,7 +73,7 @@ class SlotPickerWidget(Widget):
         context = super().get_context(name, value, attrs)
         context = super().get_context(name, value, attrs)
         event: Event = self.participant.event
         event: Event = self.participant.event
 
 
-        context['widget']['grid'] = slots2grid(event, [self.participant])
+        context['widget']['grid'] = slots2grid(event, [self.participant], True)
         return context
         return context
 
 
     def value_from_datadict(self, data, files, name):
     def value_from_datadict(self, data, files, name):