api: sort events by start_datetime in recurring events list (#59869)

This commit is contained in:
Valentin Deniaud 2021-12-22 12:26:10 +01:00
parent 8accec00fd
commit 51812ea159
3 changed files with 26 additions and 7 deletions

View File

@ -242,6 +242,10 @@ class AgendaOrSubscribedSlugsSerializer(AgendaOrSubscribedSlugsMixin, serializer
pass
class RecurringEventsListSerializer(AgendaOrSubscribedSlugsSerializer):
sort = serializers.ChoiceField(required=False, choices=['day', _('Day')])
class AgendaSlugsSerializer(serializers.Serializer):
agendas = CommaSeparatedStringField(
required=True, child=serializers.SlugField(max_length=160, allow_blank=False)

View File

@ -1089,7 +1089,7 @@ class RecurringEventsList(APIView):
if not settings.ENABLE_RECURRING_EVENT_BOOKING:
raise Http404()
serializer = serializers.AgendaOrSubscribedSlugsSerializer(data=request.query_params)
serializer = serializers.RecurringEventsListSerializer(data=request.query_params)
if not serializer.is_valid():
raise APIErrorBadRequest(N_('invalid payload'), errors=serializer.errors)
data = serializer.validated_data
@ -1108,14 +1108,18 @@ class RecurringEventsList(APIView):
agenda_slug: i for i, agenda_slug in enumerate(data['agenda_slugs'])
}
events.sort(
key=lambda event: (event.day, agenda_querystring_indexes[event.agenda.slug], event.slug)
key=lambda event: (
event.day if data.get('sort') == 'day' else event.start_datetime,
agenda_querystring_indexes[event.agenda.slug],
event.slug,
)
)
elif 'subscribed' in request.query_params:
category_querystring_indexes = {category: i for i, category in enumerate(data['subscribed'])}
sort_by_category = bool(data['subscribed'] != ['all'])
events.sort(
key=lambda event: (
event.day,
event.day if data.get('sort') == 'day' else event.start_datetime,
category_querystring_indexes[event.agenda.category.slug] if sort_by_category else None,
event.agenda.slug,
event.slug,

View File

@ -1406,7 +1406,7 @@ def test_recurring_events_api_list(app, freezer):
recurrence_end_date=now() + datetime.timedelta(days=45),
)
resp = app.get('/api/agendas/recurring-events/?agendas=%s' % agenda.slug)
resp = app.get('/api/agendas/recurring-events/?agendas=%s&sort=day' % agenda.slug)
assert len(resp.json['data']) == 4
assert resp.json['data'][0]['id'] == 'foo-bar@example-event:0'
assert resp.json['data'][0]['text'] == 'Monday: Example Event'
@ -1429,6 +1429,17 @@ def test_recurring_events_api_list(app, freezer):
assert resp.json['data'][3]['day'] == 'Friday'
assert resp.json['data'][3]['slug'] == 'example-event'
resp = app.get('/api/agendas/recurring-events/?agendas=%s' % agenda.slug)
assert len(resp.json['data']) == 4
assert resp.json['data'][0]['id'] == 'foo-bar@example-event:0'
assert resp.json['data'][1]['id'] == 'foo-bar@example-event:3'
assert resp.json['data'][2]['id'] == 'foo-bar@example-event:4'
assert resp.json['data'][3]['id'] == 'foo-bar@other:1'
resp = app.get('/api/agendas/recurring-events/?agendas=%s&sort=invalid' % agenda.slug, status=400)
assert resp.json['err'] == 1
assert resp.json['errors']['sort'][0] == '"invalid" is not a valid choice.'
event.publication_datetime = now() + datetime.timedelta(days=2)
event.save()
resp = app.get('/api/agendas/recurring-events/?agendas=%s' % agenda.slug)
@ -1466,7 +1477,7 @@ def test_recurring_events_api_list_multiple_agendas(app):
agenda=agenda2,
)
resp = app.get('/api/agendas/recurring-events/?agendas=first-agenda,second-agenda')
resp = app.get('/api/agendas/recurring-events/?agendas=first-agenda,second-agenda&sort=day')
event_ids = [x['id'] for x in resp.json['data']]
assert event_ids == [
'first-agenda@a:0',
@ -1479,7 +1490,7 @@ def test_recurring_events_api_list_multiple_agendas(app):
assert event_ids.index('first-agenda@a:2') < event_ids.index('second-agenda@c:2')
# sorting depends on querystring order
resp = app.get('/api/agendas/recurring-events/?agendas=second-agenda,first-agenda')
resp = app.get('/api/agendas/recurring-events/?agendas=second-agenda,first-agenda&sort=day')
event_ids = [x['id'] for x in resp.json['data']]
assert event_ids.index('first-agenda@a:2') > event_ids.index('second-agenda@c:2')
@ -1560,7 +1571,7 @@ def test_recurring_events_api_list_subscribed(app, user):
date_start=now(),
date_end=now() + datetime.timedelta(days=30),
)
resp = app.get('/api/agendas/recurring-events/?user_external_id=xxx&subscribed=all')
resp = app.get('/api/agendas/recurring-events/?user_external_id=xxx&subscribed=all&sort=day')
assert len(resp.json['data']) == 5
# events are sorted by day