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

@@ -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 = """
<a href="{url}" class="event">
@@ -403,36 +407,40 @@ def widgets_for_event_qs(request, qs, user, nmax):
</div>
"""
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)