From 8528b5d943bb0630c31f1081b44dc776e520d4e3 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Mon, 27 Jul 2026 21:50:15 +0200 Subject: [PATCH] Replace checkin widget --- .../event/dashboard_partial_checkin.html | 23 ++++++++ .../templates/pretixcontrol/event/index.html | 56 +++++++++++++------ .../templates/pretixcontrol/events/index.html | 2 +- .../pretixcontrol/fragment_quota_box.html | 6 +- .../fragment_quota_box_mock.html | 10 ++++ .../pretixcontrol/subevents/index.html | 2 +- src/pretix/control/urls.py | 1 + src/pretix/control/views/dashboards.py | 35 ++++-------- src/pretix/control/views/utils.py | 8 +++ 9 files changed, 101 insertions(+), 42 deletions(-) create mode 100644 src/pretix/control/templates/pretixcontrol/event/dashboard_partial_checkin.html create mode 100644 src/pretix/control/templates/pretixcontrol/fragment_quota_box_mock.html diff --git a/src/pretix/control/templates/pretixcontrol/event/dashboard_partial_checkin.html b/src/pretix/control/templates/pretixcontrol/event/dashboard_partial_checkin.html new file mode 100644 index 0000000000..bb882d90f8 --- /dev/null +++ b/src/pretix/control/templates/pretixcontrol/event/dashboard_partial_checkin.html @@ -0,0 +1,23 @@ +{% load i18n %} +{% load icon %} +{% load humanize %} +{% for cl in lists %} + + {{ cl.name }} +
+
+
+
+
+ {% icon "sign-in" %} + {{ cl.checkin_count|default_if_none:0|intcomma }} / + {{ cl.position_count|default_if_none:0|intcomma }} +
+ {% icon "user" %} + {% blocktrans trimmed with n=cl.inside_count|intcomma %} + {{ n }} present + {% endblocktrans %} +
+
+{% endfor %} diff --git a/src/pretix/control/templates/pretixcontrol/event/index.html b/src/pretix/control/templates/pretixcontrol/event/index.html index dc3af2df74..46dfba51a6 100644 --- a/src/pretix/control/templates/pretixcontrol/event/index.html +++ b/src/pretix/control/templates/pretixcontrol/event/index.html @@ -76,27 +76,51 @@ {% if not request.event.has_subevents %} {% include "pretixcontrol/event/fragment_timeline.html" %}
-
-
- {% for i in "12" %} - - - - -
-
- -
-
- {% endfor %} +
+
+
+

{% trans "Quotas" %}

+
+
+
+ {% for i in "12" %} + {% include "pretixcontrol/fragment_quota_box_mock.html" %} + {% endfor %} +
+
- Checkin-lists +
+
+

{% trans "Check-in lists" %}

+
+
+
+ {% for i in "12" %} + {% include "pretixcontrol/fragment_quota_box_mock.html" %} + {% endfor %} +
+
+
+
+
+ {% elif has_checkin_widgets %} +
+
+

{% trans "Check-in lists" %}

+
+
+
+ {% for i in "12" %} + {% include "pretixcontrol/fragment_quota_box_mock.html" %} + {% endfor %} +
- {% endif %} {% if widgets_override and 0 %} {{ widgets_override|safe }} diff --git a/src/pretix/control/templates/pretixcontrol/events/index.html b/src/pretix/control/templates/pretixcontrol/events/index.html index 067b7afaab..88fe447503 100644 --- a/src/pretix/control/templates/pretixcontrol/events/index.html +++ b/src/pretix/control/templates/pretixcontrol/events/index.html @@ -86,7 +86,7 @@ - {% trans "Paid tickets per quota" %} + {% trans "Quota utilization" %} {% trans "Status" %} diff --git a/src/pretix/control/templates/pretixcontrol/fragment_quota_box.html b/src/pretix/control/templates/pretixcontrol/fragment_quota_box.html index 09c351e291..55e7d146ff 100644 --- a/src/pretix/control/templates/pretixcontrol/fragment_quota_box.html +++ b/src/pretix/control/templates/pretixcontrol/fragment_quota_box.html @@ -1,4 +1,5 @@ {% load i18n %} +{% load humanize %} {% blocktrans with num=q.cached_avail.1 %}Currently available: {{ num }}{% endblocktrans %}{% endif %}" href="{% url "control:event.items.quotas.show" event=q.event.slug organizer=q.event.organizer.slug quota=q.pk %}"> @@ -17,6 +18,9 @@
{% endif %}
- {{ q.cached_availability_paid_orders|default_if_none:"?" }} / {{ q.size|default_if_none:"∞" }} + {{ q.used|default_if_none:"∞" }} / {{ q.size|default_if_none:"∞" }}
+ {% blocktrans trimmed with n=q.cached_availability_paid_orders %} + {{ n }} paid + {% endblocktrans %}
diff --git a/src/pretix/control/templates/pretixcontrol/fragment_quota_box_mock.html b/src/pretix/control/templates/pretixcontrol/fragment_quota_box_mock.html new file mode 100644 index 0000000000..60ab3a4cc8 --- /dev/null +++ b/src/pretix/control/templates/pretixcontrol/fragment_quota_box_mock.html @@ -0,0 +1,10 @@ + + + + +
+
+ +
+
+
diff --git a/src/pretix/control/templates/pretixcontrol/subevents/index.html b/src/pretix/control/templates/pretixcontrol/subevents/index.html index 377c395ba8..7f0babfb08 100644 --- a/src/pretix/control/templates/pretixcontrol/subevents/index.html +++ b/src/pretix/control/templates/pretixcontrol/subevents/index.html @@ -102,7 +102,7 @@ - {% trans "Paid tickets per quota" %} + {% trans "Quota utilization" %} {% trans "Status" %} diff --git a/src/pretix/control/urls.py b/src/pretix/control/urls.py index c66f228011..d41e11809b 100644 --- a/src/pretix/control/urls.py +++ b/src/pretix/control/urls.py @@ -276,6 +276,7 @@ urlpatterns = [ re_path(r'^dashboard/partials/logs$', dashboards.event_index_log_lazy, name='event.index.logs'), re_path(r'^dashboard/partials/warnings$', dashboards.event_index_warnings_lazy, name='event.index.warnings'), re_path(r'^dashboard/partials/quotas$', dashboards.event_index_quotas_lazy, name='event.index.quotas'), + re_path(r'^dashboard/partials/checkin$', dashboards.event_index_checkin_lazy, name='event.index.checkin'), re_path(r'^dashboard/partials/comment$', event.EventComment.as_view(), name='event.index.comment'), re_path(r'^live/$', event.EventLive.as_view(), name='event.live'), re_path(r'^transfer_session/$', event.EventTransferSession.as_view(), name='event.transfer_session'), diff --git a/src/pretix/control/views/dashboards.py b/src/pretix/control/views/dashboards.py index c6ccd8b65b..7ac4999997 100644 --- a/src/pretix/control/views/dashboards.py +++ b/src/pretix/control/views/dashboards.py @@ -239,29 +239,6 @@ def waitinglist_widgets(sender, subevent=None, lazy=False, **kwargs): return widgets -@receiver(signal=event_dashboard_widgets) -def checkin_widget(sender, subevent=None, lazy=False, **kwargs): - widgets = [] - qs = sender.checkin_lists.filter(subevent=subevent) - for cl in qs: - widgets.append({ - 'content': None if lazy else format_html( - NUM_WIDGET, - num='{}/{}'.format(intcomma(cl.inside_count), intcomma(cl.position_count)), - text=format_html(_('Present – {list}'), list=cl.name) - ), - 'lazy': 'checkin-{}'.format(cl.pk), - 'display_size': 'small', - 'priority': 50, - 'url': reverse('control:event.orders.checkinlists.show', kwargs={ - 'event': sender.slug, - 'organizer': sender.organizer.slug, - 'list': cl.pk - }) - }) - return widgets - - @receiver(signal=event_dashboard_widgets) def welcome_wizard_widget(sender, **kwargs): template = get_template('pretixcontrol/event/dashboard_widget_welcome.html') @@ -334,6 +311,7 @@ def event_index(request, organizer, event): ] ctx['today'] = now().astimezone(request.event.timezone).date() ctx['nearly_now'] = now().astimezone(request.event.timezone) - timedelta(seconds=20) + ctx['has_checkin_widgets'] = not request.event.has_subevents or request.event.checkin_lists.filter(subevent=None).exists() resp = render(request, 'pretixcontrol/event/index.html', ctx) return resp @@ -405,6 +383,17 @@ def event_index_quotas_lazy(request, organizer, event): ) +def event_index_checkin_lazy(request, organizer, event): + lists = request.event.checkin_lists.filter(subevent=None)[:10] + return render( + request, + 'pretixcontrol/event/dashboard_partial_checkin.html', + { + 'lists': lists, + } + ) + + def event_index_log_lazy(request, organizer, event): qs = request.event.logentry_set.all().select_related('user', 'content_type', 'api_token', 'oauth_application', 'device').order_by('-datetime') diff --git a/src/pretix/control/views/utils.py b/src/pretix/control/views/utils.py index 5f3968132d..5074728523 100644 --- a/src/pretix/control/views/utils.py +++ b/src/pretix/control/views/utils.py @@ -10,6 +10,14 @@ def prepare_quotas_for_boxes(quotas): for q in quotas: q.cached_avail = qa.results[q] q.cached_availability_paid_orders = qa.count_paid_orders.get(q, 0) + q.used = ( + qa.count_paid_orders.get(q, 0) + + qa.count_pending_orders.get(q, 0) + + qa.count_exited_orders.get(q, 0) + + qa.count_vouchers.get(q, 0) + + qa.count_waitinglist.get(q, 0) + + qa.count_cart.get(q, 0) + ) if q.size is not None: other_blocked = q.size - q.cached_availability_paid_orders - q.cached_avail[1] q.percent_paid = min(