From 97d735f8d27ec9d83e803b0c5363a4f21c4dad30 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Tue, 28 Jun 2022 14:43:28 +0200
Subject: [PATCH] manager: timesheet & activity display configuration (#66681)

---
 chrono/manager/forms.py                       |  26 +-
 chrono/manager/static/css/style.scss          |   4 +
 chrono/manager/static/css/timesheet.scss      |   4 +
 .../manager_events_timesheet_fragment.html    |  51 ++-
 tests/manager/test_event_timesheet.py         | 300 ++++++++++--------
 5 files changed, 235 insertions(+), 150 deletions(-)

diff --git a/chrono/manager/forms.py b/chrono/manager/forms.py
index 976609b6..2b878c84 100644
--- a/chrono/manager/forms.py
+++ b/chrono/manager/forms.py
@@ -562,7 +562,7 @@ class EventsTimesheetForm(forms.Form):
         initial='lastname,firstname',
     )
     date_display = forms.ChoiceField(
-        label=_('Display'),
+        label=_('Date display'),
         choices=[
             ('all', _('All on the same page')),
             ('month', _('1 month per page')),
@@ -575,6 +575,14 @@ class EventsTimesheetForm(forms.Form):
         label=_('Number of dates per page'),
         required=False,
     )
+    activity_display = forms.ChoiceField(
+        label=_('Activity display'),
+        choices=[
+            ('row', _('In line')),
+            ('col', _('In column')),
+        ],
+        initial='row',
+    )
     orientation = forms.ChoiceField(
         label=_('PDF orientation'),
         choices=[
@@ -591,6 +599,9 @@ class EventsTimesheetForm(forms.Form):
         if self.event is not None:
             del self.fields['date_start']
             del self.fields['date_end']
+            del self.fields['date_display']
+            del self.fields['custom_nb_dates_per_page']
+            del self.fields['activity_display']
 
     def get_slots(self):
         extra_data = self.cleaned_data['extra_data'].split(',')
@@ -623,27 +634,28 @@ class EventsTimesheetForm(forms.Form):
                 .select_related('primary_event')
                 .order_by('start_datetime', 'label')
             )
-        dates = set()
+        dates = defaultdict(list)
         events = []
         dates_per_event_id = defaultdict(list)
         for event in all_events:
             date = localtime(event.start_datetime).date()
-            dates.add(date)
             real_event = event.primary_event or event
+            dates[date].append(real_event)
             if real_event not in events:
                 events.append(real_event)
             dates_per_event_id[real_event.pk].append(date)
-        dates = sorted(dates)
+        dates = [(k, v) for k, v in dates.items()]
+        dates = sorted(dates, key=lambda a: a[0])
 
-        date_display = self.cleaned_data['date_display']
+        date_display = self.cleaned_data.get('date_display') or 'all'
         if date_display in ['month', 'week']:
             grouper = defaultdict(list)
-            for date in dates:
+            for date, event in dates:
                 if date_display == 'month':
                     attr = date.month
                 else:
                     attr = date.isocalendar().week
-                grouper[(date.year, attr)].append(date)
+                grouper[(date.year, attr)].append((date, event))
             dates = [grouper[g] for g in sorted(grouper.keys())]
         elif date_display == 'custom':
             n = self.cleaned_data['custom_nb_dates_per_page']
diff --git a/chrono/manager/static/css/style.scss b/chrono/manager/static/css/style.scss
index 46f207f0..fdc4ce5e 100644
--- a/chrono/manager/static/css/style.scss
+++ b/chrono/manager/static/css/style.scss
@@ -505,6 +505,10 @@ table.timesheet {
 			width: 20px;
 			text-align: center;
 		}
+		&.date-event {
+			width: 60px;
+			text-align: center;
+		}
 	}
 	td {
 		padding: 0.5em 0.5ex;
diff --git a/chrono/manager/static/css/timesheet.scss b/chrono/manager/static/css/timesheet.scss
index 819c9088..da6669fd 100644
--- a/chrono/manager/static/css/timesheet.scss
+++ b/chrono/manager/static/css/timesheet.scss
@@ -25,6 +25,10 @@ table.timesheet {
 			width: 30px;
 			text-align: center;
 		}
+		&.date-event {
+			width: 60px;
+			text-align: center;
+		}
 	}
 	td {
 		border: 0.5px solid black;
diff --git a/chrono/manager/templates/chrono/manager_events_timesheet_fragment.html b/chrono/manager/templates/chrono/manager_events_timesheet_fragment.html
index b1a2238a..da15bbd8 100644
--- a/chrono/manager/templates/chrono/manager_events_timesheet_fragment.html
+++ b/chrono/manager/templates/chrono/manager_events_timesheet_fragment.html
@@ -11,24 +11,47 @@
       <th>{% trans "First name" %}</th>
       <th>{% trans "Last name" %}</th>
       {% for k in slots.extra_data %}<th>{{ k }}</th>{% endfor %}
-      {% if events_num > 1 %}<th>{% trans "Activity" %}</th>{% endif %}
-      {% for date in dates %}<th class="date">{{ date|date:"D d/m" }}</th>{% endfor %}
+      {% if events_num > 1 and form.cleaned_data.activity_display != 'col' %}<th class="activity">{% trans "Activity" %}</th>{% endif %}
+      {% for date, events in dates %}
+        {% if form.cleaned_data.activity_display == 'col' %}
+          {% for event in events %}
+          <th class="date-event" data-id="{{ date|date:"d-m" }}:{{ event.slug }}">{% blocktrans with date=date|date:"d/m" %}{{ event }} of {{ date }}{% endblocktrans %}</th>
+          {% endfor %}
+        {% else %}
+          <th class="date" data-id="{{ date|date:"d-m" }}">{{ date|date:"D d/m" }}</th>
+        {% endif %}
+      {% endfor %}
     </tr>
   </thead>
   <tbody>
-    {% for user in grouper.users %}{% for event in user.events %}
-    <tr>
-      {% if forloop.first %}
-      <td {% if events_num > 1 %}rowspan="{{ events_num }}"{% endif %}>{{ user.user_first_name }}</td>
-      <td {% if events_num > 1 %}rowspan="{{ events_num }}"{% endif %}>{{ user.user_last_name }}</td>
-      {% for k in slots.extra_data %}<td {% if events_num > 1 %}rowspan="{{ events_num }}"{% endif %}>{{ user.extra_data|get:k }}</td>{% endfor %}
-      {% endif %}
-      {% if events_num > 1 %}<td>{{ event.event }}</td>{% endif %}
-      {% for date in dates %}
-      {% with booked=event.dates|get:date %}<td class="date">{% if booked is True %}☐{% elif booked is None %}-{% endif %}</td>{% endwith %}
+    {% if form.cleaned_data.activity_display == 'col' %}
+      {% for user in grouper.users %}
+      <tr>
+        <td>{{ user.user_first_name }}</td>
+        <td>{{ user.user_last_name }}</td>
+        {% for k in slots.extra_data %}<td>{{ user.extra_data|get:k }}</td>{% endfor %}
+        {% for date, events in dates %}
+          {% for event in events %}
+          {% for item in user.events %}{% if item.event == event %}{% with booked=item.dates|get:date %}<td class="date" data-id="{{ date|date:"d-m" }}:{{ item.event.slug }}:{{ user.user_id }}">{% if booked is True %}☐{% elif booked is None %}-{% endif %}</td>{% endwith %}{% endif %}{% endfor %}
+          {% endfor %}
+        {% endfor %}
+      </tr>
       {% endfor %}
-    </tr>
-    {% endfor %}{% endfor %}
+    {% else %}
+      {% for user in grouper.users %}{% for item in user.events %}
+      <tr>
+        {% if forloop.first %}
+        <td {% if events_num > 1 %}rowspan="{{ events_num }}"{% endif %}>{{ user.user_first_name }}</td>
+        <td {% if events_num > 1 %}rowspan="{{ events_num }}"{% endif %}>{{ user.user_last_name }}</td>
+        {% for k in slots.extra_data %}<td {% if events_num > 1 %}rowspan="{{ events_num }}"{% endif %}>{{ user.extra_data|get:k }}</td>{% endfor %}
+        {% endif %}
+        {% if events_num > 1 %}<td class="activity">{{ item.event }}</td>{% endif %}
+        {% for date, events in dates %}
+        {% with booked=item.dates|get:date %}<td class="date" data-id="{{ date|date:"d-m" }}:{{ item.event.slug }}:{{ user.user_id }}">{% if booked is True %}☐{% elif booked is None %}-{% endif %}</td>{% endwith %}
+        {% endfor %}
+      </tr>
+      {% endfor %}{% endfor %}
+    {% endif %}
   </tbody>
 </table>
 {% if form.cleaned_data.with_page_break %}{% if not forloop.last or not forloop.parentloop.last %}<div class="page_break"></div>{% endif %}{% endif %}
diff --git a/tests/manager/test_event_timesheet.py b/tests/manager/test_event_timesheet.py
index eb82737d..5e3daf2f 100644
--- a/tests/manager/test_event_timesheet.py
+++ b/tests/manager/test_event_timesheet.py
@@ -1,4 +1,5 @@
 import datetime
+import itertools
 
 import pytest
 from django.db import connection
@@ -99,21 +100,20 @@ def test_events_timesheet_slots(app, admin_user):
         assert len(ctx.captured_queries) == 7
 
     slots = resp.context['form'].get_slots()
-    assert slots['dates'] == [
-        [
-            datetime.date(2022, 2, 1),
-            datetime.date(2022, 2, 2),
-            datetime.date(2022, 2, 7),
-            datetime.date(2022, 2, 8),
-            datetime.date(2022, 2, 9),
-            datetime.date(2022, 2, 14),
-            datetime.date(2022, 2, 15),
-            datetime.date(2022, 2, 16),
-            datetime.date(2022, 2, 21),
-            datetime.date(2022, 2, 22),
-            datetime.date(2022, 2, 23),
-            datetime.date(2022, 2, 28),
-        ]
+    assert len(slots['dates']) == 1
+    assert [d[0] for d in slots['dates'][0]] == [
+        datetime.date(2022, 2, 1),
+        datetime.date(2022, 2, 2),
+        datetime.date(2022, 2, 7),
+        datetime.date(2022, 2, 8),
+        datetime.date(2022, 2, 9),
+        datetime.date(2022, 2, 14),
+        datetime.date(2022, 2, 15),
+        datetime.date(2022, 2, 16),
+        datetime.date(2022, 2, 21),
+        datetime.date(2022, 2, 22),
+        datetime.date(2022, 2, 23),
+        datetime.date(2022, 2, 28),
     ]
     assert slots['events'] == [
         event2,
@@ -131,26 +131,32 @@ def test_events_timesheet_slots(app, admin_user):
             'events': [
                 {
                     'event': event2,
-                    'dates': {date: False for date in slots['dates'][0] if date == datetime.date(2022, 2, 1)},
+                    'dates': {
+                        date: False for date, events in slots['dates'][0] if date == datetime.date(2022, 2, 1)
+                    },
                 },
                 {
                     'event': recurring_event1,
-                    'dates': {date: False for date in slots['dates'][0] if date.weekday() in [0, 1]},
+                    'dates': {date: False for date, events in slots['dates'][0] if date.weekday() in [0, 1]},
                 },
                 {
                     'event': recurring_event2,
-                    'dates': {date: False for date in slots['dates'][0] if date.weekday() in [1, 2]},
+                    'dates': {date: False for date, events in slots['dates'][0] if date.weekday() in [1, 2]},
                 },
                 {
                     'event': event3,
                     'dates': {
-                        date: False for date in slots['dates'][0] if date == datetime.date(2022, 2, 15)
+                        date: False
+                        for date, events in slots['dates'][0]
+                        if date == datetime.date(2022, 2, 15)
                     },
                 },
                 {
                     'event': event4,
                     'dates': {
-                        date: False for date in slots['dates'][0] if date == datetime.date(2022, 2, 28)
+                        date: False
+                        for date, events in slots['dates'][0]
+                        if date == datetime.date(2022, 2, 28)
                     },
                 },
             ],
@@ -202,12 +208,11 @@ def test_events_timesheet_subscription_limits(app, admin_user):
     resp = resp.form.submit()
 
     slots = resp.context['form'].get_slots()
-    assert slots['dates'] == [
-        [
-            datetime.date(2022, 2, 1),
-            datetime.date(2022, 2, 15),
-            datetime.date(2022, 2, 28),
-        ]
+    assert len(slots['dates']) == 1
+    assert [d[0] for d in slots['dates'][0]] == [
+        datetime.date(2022, 2, 1),
+        datetime.date(2022, 2, 15),
+        datetime.date(2022, 2, 28),
     ]
 
     assert slots['events'] == [
@@ -507,6 +512,45 @@ def test_events_timesheet_booked(app, admin_user):
         },
     ]
 
+    # activity_display: row
+    assert len(resp.pyquery.find('th.activity')) == 1
+    assert resp.pyquery.find('th.activity')[0].text == 'Activity'
+    assert len(resp.pyquery.find('th.date')) == 1
+    assert len(resp.pyquery.find('th.date-event')) == 0
+    assert resp.pyquery.find('th.date[data-id="15-02"]')[0].text == 'Tue 15/02'
+    assert len(resp.pyquery.find('td.activity')) == 5
+    assert resp.pyquery.find('td.activity')[0].text == 'event 1'
+    assert resp.pyquery.find('td.activity')[1].text == 'event 2'
+    assert resp.pyquery.find('td.activity')[2].text == 'event 3'
+    assert resp.pyquery.find('td.activity')[3].text == 'recurring 1'
+    assert resp.pyquery.find('td.activity')[4].text == 'recurring 2'
+    assert len(resp.pyquery.find('td.date')) == 5
+    assert resp.pyquery.find('td.date[data-id="15-02:event-1:user:1"]')[0].text == '☐'
+    assert resp.pyquery.find('td.date[data-id="15-02:event-2:user:1"]')[0].text is None
+    assert resp.pyquery.find('td.date[data-id="15-02:event-3:user:1"]')[0].text is None
+    assert resp.pyquery.find('td.date[data-id="15-02:recurring-1:user:1"]')[0].text == '☐'
+    assert resp.pyquery.find('td.date[data-id="15-02:recurring-2:user:1"]')[0].text is None
+
+    # activity_display: col
+    resp.form['activity_display'] = 'col'
+    resp = resp.form.submit()
+    new_slots = resp.context['form'].get_slots()
+    assert new_slots == slots
+    assert len(resp.pyquery.find('th.activity')) == 0
+    assert len(resp.pyquery.find('th.date')) == 0
+    assert len(resp.pyquery.find('th.date-event')) == 5
+    assert resp.pyquery.find('th.date-event[data-id="15-02:event-1"]')[0].text == 'event 1 of 15/02'
+    assert resp.pyquery.find('th.date-event[data-id="15-02:event-2"]')[0].text == 'event 2 of 15/02'
+    assert resp.pyquery.find('th.date-event[data-id="15-02:event-3"]')[0].text == 'event 3 of 15/02'
+    assert resp.pyquery.find('th.date-event[data-id="15-02:recurring-1"]')[0].text == 'recurring 1 of 15/02'
+    assert resp.pyquery.find('th.date-event[data-id="15-02:recurring-2"]')[0].text == 'recurring 2 of 15/02'
+    assert len(resp.pyquery.find('td.date')) == 5
+    assert resp.pyquery.find('td.date[data-id="15-02:event-1:user:1"]')[0].text == '☐'
+    assert resp.pyquery.find('td.date[data-id="15-02:event-2:user:1"]')[0].text is None
+    assert resp.pyquery.find('td.date[data-id="15-02:event-3:user:1"]')[0].text is None
+    assert resp.pyquery.find('td.date[data-id="15-02:recurring-1:user:1"]')[0].text == '☐'
+    assert resp.pyquery.find('td.date[data-id="15-02:recurring-2:user:1"]')[0].text is None
+
 
 def test_events_timesheet_extra_data(app, admin_user):
     agenda = Agenda.objects.create(label='Events', kind='events')
@@ -732,48 +776,46 @@ def test_events_timesheet_date_display(app, admin_user):
     resp = resp.form.submit()
     slots = resp.context['form'].get_slots()
 
-    assert slots['dates'] == [
-        [
-            datetime.date(2022, 1, 3),
-            datetime.date(2022, 1, 10),
-            datetime.date(2022, 1, 17),
-            datetime.date(2022, 1, 24),
-            datetime.date(2022, 1, 31),
-            datetime.date(2022, 2, 7),
-            datetime.date(2022, 2, 14),
-            datetime.date(2022, 2, 21),
-            datetime.date(2022, 2, 28),
-            datetime.date(2022, 3, 7),
-            datetime.date(2022, 3, 14),
-            datetime.date(2022, 3, 21),
-            datetime.date(2022, 3, 28),
-        ]
+    assert len(slots['dates']) == 1
+    assert [d[0] for d in slots['dates'][0]] == [
+        datetime.date(2022, 1, 3),
+        datetime.date(2022, 1, 10),
+        datetime.date(2022, 1, 17),
+        datetime.date(2022, 1, 24),
+        datetime.date(2022, 1, 31),
+        datetime.date(2022, 2, 7),
+        datetime.date(2022, 2, 14),
+        datetime.date(2022, 2, 21),
+        datetime.date(2022, 2, 28),
+        datetime.date(2022, 3, 7),
+        datetime.date(2022, 3, 14),
+        datetime.date(2022, 3, 21),
+        datetime.date(2022, 3, 28),
     ]
 
     resp.form['date_display'] = 'month'
     resp = resp.form.submit()
     slots = resp.context['form'].get_slots()
 
-    assert slots['dates'] == [
-        [
-            datetime.date(2022, 1, 3),
-            datetime.date(2022, 1, 10),
-            datetime.date(2022, 1, 17),
-            datetime.date(2022, 1, 24),
-            datetime.date(2022, 1, 31),
-        ],
-        [
-            datetime.date(2022, 2, 7),
-            datetime.date(2022, 2, 14),
-            datetime.date(2022, 2, 21),
-            datetime.date(2022, 2, 28),
-        ],
-        [
-            datetime.date(2022, 3, 7),
-            datetime.date(2022, 3, 14),
-            datetime.date(2022, 3, 21),
-            datetime.date(2022, 3, 28),
-        ],
+    assert len(slots['dates']) == 3
+    assert [d[0] for d in slots['dates'][0]] == [
+        datetime.date(2022, 1, 3),
+        datetime.date(2022, 1, 10),
+        datetime.date(2022, 1, 17),
+        datetime.date(2022, 1, 24),
+        datetime.date(2022, 1, 31),
+    ]
+    assert [d[0] for d in slots['dates'][1]] == [
+        datetime.date(2022, 2, 7),
+        datetime.date(2022, 2, 14),
+        datetime.date(2022, 2, 21),
+        datetime.date(2022, 2, 28),
+    ]
+    assert [d[0] for d in slots['dates'][2]] == [
+        datetime.date(2022, 3, 7),
+        datetime.date(2022, 3, 14),
+        datetime.date(2022, 3, 21),
+        datetime.date(2022, 3, 28),
     ]
 
     resp.form['date_display'] = 'week'
@@ -781,20 +823,21 @@ def test_events_timesheet_date_display(app, admin_user):
     slots = resp.context['form'].get_slots()
     assert resp.text.count('<div class="page_break">') == 12
 
-    assert slots['dates'] == [
-        [datetime.date(2022, 1, 3)],
-        [datetime.date(2022, 1, 10)],
-        [datetime.date(2022, 1, 17)],
-        [datetime.date(2022, 1, 24)],
-        [datetime.date(2022, 1, 31)],
-        [datetime.date(2022, 2, 7)],
-        [datetime.date(2022, 2, 14)],
-        [datetime.date(2022, 2, 21)],
-        [datetime.date(2022, 2, 28)],
-        [datetime.date(2022, 3, 7)],
-        [datetime.date(2022, 3, 14)],
-        [datetime.date(2022, 3, 21)],
-        [datetime.date(2022, 3, 28)],
+    assert len(slots['dates']) == 13
+    assert [d[0] for d in itertools.chain(*slots['dates'])] == [
+        datetime.date(2022, 1, 3),
+        datetime.date(2022, 1, 10),
+        datetime.date(2022, 1, 17),
+        datetime.date(2022, 1, 24),
+        datetime.date(2022, 1, 31),
+        datetime.date(2022, 2, 7),
+        datetime.date(2022, 2, 14),
+        datetime.date(2022, 2, 21),
+        datetime.date(2022, 2, 28),
+        datetime.date(2022, 3, 7),
+        datetime.date(2022, 3, 14),
+        datetime.date(2022, 3, 21),
+        datetime.date(2022, 3, 28),
     ]
 
     resp.form['date_display'] = 'custom'
@@ -805,54 +848,52 @@ def test_events_timesheet_date_display(app, admin_user):
     resp = resp.form.submit()
     slots = resp.context['form'].get_slots()
 
-    assert slots['dates'] == [
-        [
-            datetime.date(2022, 1, 3),
-            datetime.date(2022, 1, 10),
-            datetime.date(2022, 1, 17),
-            datetime.date(2022, 1, 24),
-            datetime.date(2022, 1, 31),
-            datetime.date(2022, 2, 7),
-            datetime.date(2022, 2, 14),
-            datetime.date(2022, 2, 21),
-            datetime.date(2022, 2, 28),
-            datetime.date(2022, 3, 7),
-        ],
-        [
-            datetime.date(2022, 3, 14),
-            datetime.date(2022, 3, 21),
-            datetime.date(2022, 3, 28),
-        ],
+    assert len(slots['dates']) == 2
+    assert [d[0] for d in slots['dates'][0]] == [
+        datetime.date(2022, 1, 3),
+        datetime.date(2022, 1, 10),
+        datetime.date(2022, 1, 17),
+        datetime.date(2022, 1, 24),
+        datetime.date(2022, 1, 31),
+        datetime.date(2022, 2, 7),
+        datetime.date(2022, 2, 14),
+        datetime.date(2022, 2, 21),
+        datetime.date(2022, 2, 28),
+        datetime.date(2022, 3, 7),
+    ]
+    assert [d[0] for d in slots['dates'][1]] == [
+        datetime.date(2022, 3, 14),
+        datetime.date(2022, 3, 21),
+        datetime.date(2022, 3, 28),
     ]
 
     resp.form['custom_nb_dates_per_page'] = 3
     resp = resp.form.submit()
     slots = resp.context['form'].get_slots()
 
-    assert slots['dates'] == [
-        [
-            datetime.date(2022, 1, 3),
-            datetime.date(2022, 1, 10),
-            datetime.date(2022, 1, 17),
-        ],
-        [
-            datetime.date(2022, 1, 24),
-            datetime.date(2022, 1, 31),
-            datetime.date(2022, 2, 7),
-        ],
-        [
-            datetime.date(2022, 2, 14),
-            datetime.date(2022, 2, 21),
-            datetime.date(2022, 2, 28),
-        ],
-        [
-            datetime.date(2022, 3, 7),
-            datetime.date(2022, 3, 14),
-            datetime.date(2022, 3, 21),
-        ],
-        [
-            datetime.date(2022, 3, 28),
-        ],
+    assert len(slots['dates']) == 5
+    assert [d[0] for d in slots['dates'][0]] == [
+        datetime.date(2022, 1, 3),
+        datetime.date(2022, 1, 10),
+        datetime.date(2022, 1, 17),
+    ]
+    assert [d[0] for d in slots['dates'][1]] == [
+        datetime.date(2022, 1, 24),
+        datetime.date(2022, 1, 31),
+        datetime.date(2022, 2, 7),
+    ]
+    assert [d[0] for d in slots['dates'][2]] == [
+        datetime.date(2022, 2, 14),
+        datetime.date(2022, 2, 21),
+        datetime.date(2022, 2, 28),
+    ]
+    assert [d[0] for d in slots['dates'][3]] == [
+        datetime.date(2022, 3, 7),
+        datetime.date(2022, 3, 14),
+        datetime.date(2022, 3, 21),
+    ]
+    assert [d[0] for d in slots['dates'][4]] == [
+        datetime.date(2022, 3, 28),
     ]
 
     Subscription.objects.create(
@@ -881,8 +922,8 @@ def test_events_timesheet_pdf(app, admin_user):
 
     login(app)
     resp = app.get(
-        '/manage/agendas/%s/events/timesheet?pdf=&date_start=2022-02-01&date_end=2022-02-28&sort=lastname,firstname&date_display=all&orientation=portrait'
-        % agenda.pk
+        '/manage/agendas/%s/events/timesheet?pdf=&date_start=2022-02-01&date_end=2022-02-28&sort=lastname,firstname'
+        '&date_display=all&activity_display=row&orientation=portrait' % agenda.pk
     )
     assert resp.headers['Content-Type'] == 'application/pdf'
     assert (
@@ -892,7 +933,7 @@ def test_events_timesheet_pdf(app, admin_user):
 
     # form invalid
     resp = app.get(
-        '/manage/agendas/%s/events/timesheet?pdf=&date_start=2022-02-01&date_end=2022-02-28&sort=lastname,firstname&date_display=all'
+        '/manage/agendas/%s/events/timesheet?pdf=&date_start=2022-02-01&date_end=2022-02-28&sort=lastname,firstname&date_display=all&activity_display=row'
         % agenda.pk
     )
     assert resp.context['form'].errors['orientation'] == ['This field is required.']
@@ -946,6 +987,9 @@ def test_event_timesheet_form(app, admin_user):
     resp = app.get('/manage/agendas/%s/events/%s/timesheet' % (agenda.pk, event.pk))
     assert 'date_start' not in resp.context['form'].fields
     assert 'date_end' not in resp.context['form'].fields
+    assert 'date_display' not in resp.context['form'].fields
+    assert 'custom_nb_dates_per_page' not in resp.context['form'].fields
+    assert 'activity_display' not in resp.context['form'].fields
     assert resp.context['form'].errors == {}
 
 
@@ -970,10 +1014,9 @@ def test_event_timesheet_slots(app, admin_user):
         assert len(ctx.captured_queries) == 7
 
     slots = resp.context['form'].get_slots()
-    assert slots['dates'] == [
-        [
-            datetime.date(2022, 2, 15),
-        ]
+    assert len(slots['dates']) == 1
+    assert [d[0] for d in slots['dates'][0]] == [
+        datetime.date(2022, 2, 15),
     ]
     assert slots['events'] == [event]
     assert slots['users'][0]['users'] == [
@@ -1027,10 +1070,9 @@ def test_event_timesheet_subscription_limits(app, admin_user):
     resp = resp.form.submit()
 
     slots = resp.context['form'].get_slots()
-    assert slots['dates'] == [
-        [
-            datetime.date(2022, 2, 15),
-        ]
+    assert len(slots['dates']) == 1
+    assert [d[0] for d in slots['dates'][0]] == [
+        datetime.date(2022, 2, 15),
     ]
 
     assert slots['events'] == [
-- 
2.35.1

