Lazy-load widgets on global dashboard

This commit is contained in:
Raphael Michel
2019-10-06 11:46:42 +02:00
parent 4ade9d39cd
commit 82497cfb89
3 changed files with 123 additions and 53 deletions

View File

@@ -20,9 +20,13 @@
</a> </a>
</div> </div>
{% for w in upcoming %} {% for w in upcoming %}
<div class="widget-{{ w.display_size|default:"small" }} {{ w.container_class|default:"widget-container" }}"> <div class="widget-{{ w.display_size|default:"small" }} {{ w.container_class|default:"widget-container" }} {% if w.lazy %}widget-lazy-loading{% endif %}" data-lazy-id="{{ w.lazy }}">
<div class="widget"> <div class="widget">
{% if w.lazy %}
<span class="fa fa-cog fa-4x"></span>
{% else %}
{{ w.content|safe }} {{ w.content|safe }}
{% endif %}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
@@ -38,9 +42,13 @@
<h2>{% trans "Your most recent events" %}</h2> <h2>{% trans "Your most recent events" %}</h2>
<div class="dashboard"> <div class="dashboard">
{% for w in past %} {% for w in past %}
<div class="widget-{{ w.display_size|default:"small" }} {{ w.container_class|default:"widget-container" }}"> <div class="widget-{{ w.display_size|default:"small" }} {{ w.container_class|default:"widget-container" }} {% if w.lazy %}widget-lazy-loading{% endif %}" data-lazy-id="{{ w.lazy }}">
<div class="widget"> <div class="widget">
{% if w.lazy %}
<span class="fa fa-cog fa-4x"></span>
{% else %}
{{ w.content|safe }} {{ w.content|safe }}
{% endif %}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
@@ -55,9 +63,13 @@
<h2>{% trans "Your event series" %}</h2> <h2>{% trans "Your event series" %}</h2>
<div class="dashboard"> <div class="dashboard">
{% for w in series %} {% for w in series %}
<div class="widget-{{ w.display_size|default:"small" }} {{ w.container_class|default:"widget-container" }}"> <div class="widget-{{ w.display_size|default:"small" }} {{ w.container_class|default:"widget-container" }} {% if w.lazy %}widget-lazy-loading{% endif %}" data-lazy-id="{{ w.lazy }}">
<div class="widget"> <div class="widget">
{% if w.lazy %}
<span class="fa fa-cog fa-4x"></span>
{% else %}
{{ w.content|safe }} {{ w.content|safe }}
{% endif %}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
@@ -72,14 +84,22 @@
<h2>{% trans "Other features" %}</h2> <h2>{% trans "Other features" %}</h2>
<div class="dashboard"> <div class="dashboard">
{% for w in widgets %} {% for w in widgets %}
<div class="widget-{{ w.display_size|default:"small" }} {{ w.container_class|default:"widget-container" }}"> <div class="widget-{{ w.display_size|default:"small" }} {{ w.container_class|default:"widget-container" }} {% if w.lazy %}widget-lazy-loading{% endif %}" data-lazy-id="{{ w.lazy }}">
{% if w.url %} {% if w.url %}
<a href="{{ w.url }}" class="widget"> <a href="{{ w.url }}" class="widget">
{% if w.lazy %}
<span class="fa fa-cog fa-4x"></span>
{% else %}
{{ w.content|safe }} {{ w.content|safe }}
{% endif %}
</a> </a>
{% else %} {% else %}
<div class="widget"> <div class="widget">
{% if w.lazy %}
<span class="fa fa-cog fa-4x"></span>
{% else %}
{{ w.content|safe }} {{ w.content|safe }}
{% endif %}
</div> </div>
{% endif %} {% endif %}
</div> </div>

View File

@@ -15,6 +15,7 @@ urlpatterns = [
url(r'^forgot$', auth.Forgot.as_view(), name='auth.forgot'), url(r'^forgot$', auth.Forgot.as_view(), name='auth.forgot'),
url(r'^forgot/recover$', auth.Recover.as_view(), name='auth.forgot.recover'), url(r'^forgot/recover$', auth.Recover.as_view(), name='auth.forgot.recover'),
url(r'^$', dashboards.user_index, name='index'), 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/settings/$', global_settings.GlobalSettingsView.as_view(), name='global.settings'),
url(r'^global/update/$', global_settings.UpdateCheckView.as_view(), name='global.update'), url(r'^global/update/$', global_settings.UpdateCheckView.as_view(), name='global.update'),
url(r'^global/message/$', global_settings.MessageView.as_view(), name='global.message'), url(r'^global/message/$', global_settings.MessageView.as_view(), name='global.message'),

View File

@@ -352,7 +352,7 @@ def event_index_widgets_lazy(request, organizer, event):
return JsonResponse({'widgets': widgets}) return JsonResponse({'widgets': widgets})
def annotated_event_query(request): def annotated_event_query(request, lazy=False):
active_orders = Order.objects.filter( active_orders = Order.objects.filter(
event=OuterRef('pk'), event=OuterRef('pk'),
status__in=[Order.STATUS_PENDING, Order.STATUS_PAID] status__in=[Order.STATUS_PENDING, Order.STATUS_PAID]
@@ -366,10 +366,13 @@ def annotated_event_query(request):
event=OuterRef('pk'), event=OuterRef('pk'),
done=False done=False
) )
qs = request.user.get_events_with_any_permission(request).annotate( qs = request.user.get_events_with_any_permission(request)
if not lazy:
qs = qs.annotate(
order_count=Subquery(active_orders, output_field=IntegerField()), order_count=Subquery(active_orders, output_field=IntegerField()),
has_ra=Exists(required_actions) has_ra=Exists(required_actions)
).annotate( )
qs = qs.annotate(
min_from=Min('subevents__date_from'), min_from=Min('subevents__date_from'),
max_from=Max('subevents__date_from'), max_from=Max('subevents__date_from'),
max_to=Max('subevents__date_to'), max_to=Max('subevents__date_to'),
@@ -380,10 +383,11 @@ def annotated_event_query(request):
return qs return qs
def widgets_for_event_qs(request, qs, user, nmax): def widgets_for_event_qs(request, qs, user, nmax, lazy=False):
widgets = [] widgets = []
# Get set of events where we have the permission to show the # of orders # Get set of events where we have the permission to show the # of orders
if not lazy:
events_with_orders = set(qs.filter( 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(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)) | Q(id__in=user.teams.filter(can_view_orders=True).values_list('limit_events__id', flat=True))
@@ -403,10 +407,14 @@ def widgets_for_event_qs(request, qs, user, nmax):
</div> </div>
""" """
if lazy:
events = qs[:nmax]
else:
events = qs.prefetch_related( events = qs.prefetch_related(
'_settings_objects', 'organizer___settings_objects' '_settings_objects', 'organizer___settings_objects'
).select_related('organizer')[:nmax] ).select_related('organizer')[:nmax]
for event in events: for event in events:
if not lazy:
tzname = event.cache.get_or_set('timezone', lambda: event.settings.timezone) tzname = event.cache.get_or_set('timezone', lambda: event.settings.timezone)
tz = pytz.timezone(tzname) tz = pytz.timezone(tzname)
if event.has_subevents: if event.has_subevents:
@@ -463,8 +471,9 @@ def widgets_for_event_qs(request, qs, user, nmax):
daterange=dr, daterange=dr,
status=status[1], status=status[1],
statusclass=status[0], statusclass=status[0],
), ) if not lazy else '',
'display_size': 'small', 'display_size': 'small',
'lazy': 'event-{}'.format(event.pk),
'priority': 100, 'priority': 100,
'container_class': 'widget-container widget-container-event', 'container_class': 'widget-container widget-container-event',
}) })
@@ -482,14 +491,9 @@ def widgets_for_event_qs(request, qs, user, nmax):
return widgets return widgets
def user_index(request): def user_index_widgets_lazy(request):
widgets = [] widgets = []
for r, result in user_dashboard_widgets.send(request, user=request.user): widgets += widgets_for_event_qs(
widgets.extend(result)
ctx = {
'widgets': rearrange(widgets),
'upcoming': widgets_for_event_qs(
request, request,
annotated_event_query(request).filter( annotated_event_query(request).filter(
Q(has_subevents=False) & Q(has_subevents=False) &
@@ -500,8 +504,8 @@ def user_index(request):
).order_by('date_from'), ).order_by('date_from'),
request.user, request.user,
7 7
), )
'past': widgets_for_event_qs( widgets += widgets_for_event_qs(
request, request,
annotated_event_query(request).filter( annotated_event_query(request).filter(
Q(has_subevents=False) & Q(has_subevents=False) &
@@ -512,14 +516,59 @@ def user_index(request):
).order_by('-order_to'), ).order_by('-order_to'),
request.user, request.user,
8 8
), )
'series': widgets_for_event_qs( widgets += widgets_for_event_qs(
request, request,
annotated_event_query(request).filter( annotated_event_query(request).filter(
has_subevents=True has_subevents=True
).order_by('-order_to'), ).order_by('-order_to'),
request.user, request.user,
8 8
)
return JsonResponse({'widgets': widgets})
def user_index(request):
widgets = []
for r, result in user_dashboard_widgets.send(request, user=request.user):
widgets.extend(result)
ctx = {
'widgets': rearrange(widgets),
'upcoming': widgets_for_event_qs(
request,
annotated_event_query(request, lazy=True).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,
lazy=True
),
'past': widgets_for_event_qs(
request,
annotated_event_query(request, lazy=True).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,
lazy=True
),
'series': widgets_for_event_qs(
request,
annotated_event_query(request, lazy=True).filter(
has_subevents=True
).order_by('-order_to'),
request.user,
8,
lazy=True
), ),
} }
return render(request, 'pretixcontrol/dashboard.html', ctx) return render(request, 'pretixcontrol/dashboard.html', ctx)