From 82497cfb893e8ee6fdd53b6eac9dab95c22e9065 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Sun, 6 Oct 2019 11:46:42 +0200 Subject: [PATCH] Lazy-load widgets on global dashboard --- .../templates/pretixcontrol/dashboard.html | 38 +++-- src/pretix/control/urls.py | 1 + src/pretix/control/views/dashboards.py | 137 ++++++++++++------ 3 files changed, 123 insertions(+), 53 deletions(-) diff --git a/src/pretix/control/templates/pretixcontrol/dashboard.html b/src/pretix/control/templates/pretixcontrol/dashboard.html index 1f2d140e95..1cc7d95bfd 100644 --- a/src/pretix/control/templates/pretixcontrol/dashboard.html +++ b/src/pretix/control/templates/pretixcontrol/dashboard.html @@ -20,9 +20,13 @@ {% for w in upcoming %} -
+
- {{ w.content|safe }} + {% if w.lazy %} + + {% else %} + {{ w.content|safe }} + {% endif %}
{% endfor %} @@ -38,9 +42,13 @@

{% trans "Your most recent events" %}

{% for w in past %} -
+
- {{ w.content|safe }} + {% if w.lazy %} + + {% else %} + {{ w.content|safe }} + {% endif %}
{% endfor %} @@ -55,9 +63,13 @@

{% trans "Your event series" %}

{% for w in series %} -
+
- {{ w.content|safe }} + {% if w.lazy %} + + {% else %} + {{ w.content|safe }} + {% endif %}
{% endfor %} @@ -72,14 +84,22 @@

{% trans "Other features" %}

{% for w in widgets %} -
+
{% if w.url %} - {{ w.content|safe }} + {% if w.lazy %} + + {% else %} + {{ w.content|safe }} + {% endif %} {% else %}
- {{ w.content|safe }} + {% if w.lazy %} + + {% else %} + {{ w.content|safe }} + {% endif %}
{% endif %}
diff --git a/src/pretix/control/urls.py b/src/pretix/control/urls.py index 9aced408c3..3941a34671 100644 --- a/src/pretix/control/urls.py +++ b/src/pretix/control/urls.py @@ -15,6 +15,7 @@ urlpatterns = [ url(r'^forgot$', auth.Forgot.as_view(), name='auth.forgot'), url(r'^forgot/recover$', auth.Recover.as_view(), name='auth.forgot.recover'), url(r'^$', dashboards.user_index, name='index'), + url(r'^widgets.json$', dashboards.user_index_widgets_lazy, name='index.widgets'), url(r'^global/settings/$', global_settings.GlobalSettingsView.as_view(), name='global.settings'), url(r'^global/update/$', global_settings.UpdateCheckView.as_view(), name='global.update'), url(r'^global/message/$', global_settings.MessageView.as_view(), name='global.message'), diff --git a/src/pretix/control/views/dashboards.py b/src/pretix/control/views/dashboards.py index 1354a441be..844c82f738 100644 --- a/src/pretix/control/views/dashboards.py +++ b/src/pretix/control/views/dashboards.py @@ -352,7 +352,7 @@ def event_index_widgets_lazy(request, organizer, event): return JsonResponse({'widgets': widgets}) -def annotated_event_query(request): +def annotated_event_query(request, lazy=False): active_orders = Order.objects.filter( event=OuterRef('pk'), status__in=[Order.STATUS_PENDING, Order.STATUS_PAID] @@ -366,10 +366,13 @@ def annotated_event_query(request): event=OuterRef('pk'), done=False ) - qs = request.user.get_events_with_any_permission(request).annotate( - order_count=Subquery(active_orders, output_field=IntegerField()), - has_ra=Exists(required_actions) - ).annotate( + qs = request.user.get_events_with_any_permission(request) + if not lazy: + qs = qs.annotate( + order_count=Subquery(active_orders, output_field=IntegerField()), + has_ra=Exists(required_actions) + ) + qs = qs.annotate( min_from=Min('subevents__date_from'), max_from=Max('subevents__date_from'), max_to=Max('subevents__date_to'), @@ -380,14 +383,15 @@ def annotated_event_query(request): return qs -def widgets_for_event_qs(request, qs, user, nmax): +def widgets_for_event_qs(request, qs, user, nmax, lazy=False): widgets = [] # Get set of events where we have the permission to show the # of orders - events_with_orders = set(qs.filter( - Q(organizer_id__in=user.teams.filter(all_events=True, can_view_orders=True).values_list('organizer', flat=True)) - | Q(id__in=user.teams.filter(can_view_orders=True).values_list('limit_events__id', flat=True)) - ).values_list('id', flat=True)) + if not lazy: + events_with_orders = set(qs.filter( + Q(organizer_id__in=user.teams.filter(all_events=True, can_view_orders=True).values_list('organizer', flat=True)) + | Q(id__in=user.teams.filter(can_view_orders=True).values_list('limit_events__id', flat=True)) + ).values_list('id', flat=True)) tpl = """ @@ -403,36 +407,40 @@ def widgets_for_event_qs(request, qs, user, nmax):
""" - events = qs.prefetch_related( - '_settings_objects', 'organizer___settings_objects' - ).select_related('organizer')[:nmax] + if lazy: + events = qs[:nmax] + else: + events = qs.prefetch_related( + '_settings_objects', 'organizer___settings_objects' + ).select_related('organizer')[:nmax] for event in events: - tzname = event.cache.get_or_set('timezone', lambda: event.settings.timezone) - tz = pytz.timezone(tzname) - if event.has_subevents: - if event.min_from is None: - dr = pgettext("subevent", "No dates") + if not lazy: + tzname = event.cache.get_or_set('timezone', lambda: event.settings.timezone) + tz = pytz.timezone(tzname) + if event.has_subevents: + if event.min_from is None: + dr = pgettext("subevent", "No dates") + else: + dr = daterange( + (event.min_from).astimezone(tz), + (event.max_fromto or event.max_to or event.max_from).astimezone(tz) + ) else: - dr = daterange( - (event.min_from).astimezone(tz), - (event.max_fromto or event.max_to or event.max_from).astimezone(tz) - ) - else: - if event.date_to: - dr = daterange(event.date_from.astimezone(tz), event.date_to.astimezone(tz)) - else: - dr = date_format(event.date_from.astimezone(tz), "DATE_FORMAT") + if event.date_to: + dr = daterange(event.date_from.astimezone(tz), event.date_to.astimezone(tz)) + else: + dr = date_format(event.date_from.astimezone(tz), "DATE_FORMAT") - if event.has_ra: - status = ('danger', _('Action required')) - elif not event.live: - status = ('warning', _('Shop disabled')) - elif event.presale_has_ended: - status = ('default', _('Sale over')) - elif not event.presale_is_running: - status = ('default', _('Soon')) - else: - status = ('success', _('On sale')) + if event.has_ra: + status = ('danger', _('Action required')) + elif not event.live: + status = ('warning', _('Shop disabled')) + elif event.presale_has_ended: + status = ('default', _('Sale over')) + elif not event.presale_is_running: + status = ('default', _('Soon')) + else: + status = ('success', _('On sale')) widgets.append({ 'content': tpl.format( @@ -463,8 +471,9 @@ def widgets_for_event_qs(request, qs, user, nmax): daterange=dr, status=status[1], statusclass=status[0], - ), + ) if not lazy else '', 'display_size': 'small', + 'lazy': 'event-{}'.format(event.pk), 'priority': 100, 'container_class': 'widget-container widget-container-event', }) @@ -482,6 +491,43 @@ def widgets_for_event_qs(request, qs, user, nmax): return widgets +def user_index_widgets_lazy(request): + widgets = [] + widgets += widgets_for_event_qs( + request, + annotated_event_query(request).filter( + Q(has_subevents=False) & + Q( + Q(Q(date_to__isnull=True) & Q(date_from__gte=now())) + | Q(Q(date_to__isnull=False) & Q(date_to__gte=now())) + ) + ).order_by('date_from'), + request.user, + 7 + ) + widgets += widgets_for_event_qs( + request, + annotated_event_query(request).filter( + Q(has_subevents=False) & + Q( + Q(Q(date_to__isnull=True) & Q(date_from__lt=now())) + | Q(Q(date_to__isnull=False) & Q(date_to__lt=now())) + ) + ).order_by('-order_to'), + request.user, + 8 + ) + widgets += widgets_for_event_qs( + request, + annotated_event_query(request).filter( + has_subevents=True + ).order_by('-order_to'), + request.user, + 8 + ) + return JsonResponse({'widgets': widgets}) + + def user_index(request): widgets = [] for r, result in user_dashboard_widgets.send(request, user=request.user): @@ -491,7 +537,7 @@ def user_index(request): 'widgets': rearrange(widgets), 'upcoming': widgets_for_event_qs( request, - annotated_event_query(request).filter( + annotated_event_query(request, lazy=True).filter( Q(has_subevents=False) & Q( Q(Q(date_to__isnull=True) & Q(date_from__gte=now())) @@ -499,11 +545,12 @@ def user_index(request): ) ).order_by('date_from'), request.user, - 7 + 7, + lazy=True ), 'past': widgets_for_event_qs( request, - annotated_event_query(request).filter( + annotated_event_query(request, lazy=True).filter( Q(has_subevents=False) & Q( Q(Q(date_to__isnull=True) & Q(date_from__lt=now())) @@ -511,15 +558,17 @@ def user_index(request): ) ).order_by('-order_to'), request.user, - 8 + 8, + lazy=True ), 'series': widgets_for_event_qs( request, - annotated_event_query(request).filter( + annotated_event_query(request, lazy=True).filter( has_subevents=True ).order_by('-order_to'), request.user, - 8 + 8, + lazy=True ), } return render(request, 'pretixcontrol/dashboard.html', ctx)