From 41cadbcfa92bec87a88b9a6e8bff40c08c590377 Mon Sep 17 00:00:00 2001 From: Thomas JUND Date: Tue, 12 Mar 2024 17:01:18 +0100 Subject: [PATCH] manager: improve html & CSS of partial booking month view (#79863) --- chrono/manager/static/css/style.scss | 79 ++++++++++++++++--- .../manager_partial_bookings_month_view.html | 67 ++++++++++------ chrono/manager/views.py | 1 + tests/manager/test_partial_bookings.py | 23 ++++-- 4 files changed, 129 insertions(+), 41 deletions(-) diff --git a/chrono/manager/static/css/style.scss b/chrono/manager/static/css/style.scss index 9928db6e..678aee82 100644 --- a/chrono/manager/static/css/style.scss +++ b/chrono/manager/static/css/style.scss @@ -870,20 +870,73 @@ div#main-content.partial-booking-dayview { background-color: var(--red); z-index: 3; } -} -.agenda-table.partial-bookings .booking { - height: 70%; - width: 100%; - position: absolute; - right: 0; - top: 15%; - background: #1066bc; - &.present { - background: hsl(120, 57%, 35%); - } - &.absent { - background: hsl(355, 80%, 45%); + // Month view, table element + &-month { + width: 100%; + border-spacing: 0; + & col.we { + background-color: var(--zebra-color); + } + & col.today { + background-image: linear-gradient( + 135deg, + hsl(65, 65%, 94%) 20%, + hsl(65, 55%, 92%) 70%, + hsl(65, 50%, 90%) 90%); + } + &--day { + padding: .33em; + a { + color: var(--font-color); + font-weight: normal; + text-decoration: none; + } + &.today a { + font-weight: bold; + } + } + & .registrant { + &--name { + box-sizing: border-box; + text-align: right; + padding: .66rem; + font-size: 130%; + color: #505050; + font-weight: normal; + width: var(--registrant-name-width); + } + &--day-cell { + border-left: var(--separator-size) solid var(--separator-color); + text-align: center; + vertical-align: middle; + padding: .33em; + line-height: 0; + & .booking { + display: inline-block; + width: Min(100%, 1.75em); + height: 1.75em; + --booking-color: #1066bc; + background-color: var(--booking-color); + &.present { + background: var(--green); + } + &.absent { + background: var(--red); + } + } + } + } + &--registrant:nth-child(odd) { + & th, & td { + background-color: var(--zebra-color); + } + } + &--registrant:nth-child(even) { + & th, & td { + --separator-color: var(--zebra-color); + } + } } } diff --git a/chrono/manager/templates/chrono/manager_partial_bookings_month_view.html b/chrono/manager/templates/chrono/manager_partial_bookings_month_view.html index 728c27f4..4c103ce6 100644 --- a/chrono/manager/templates/chrono/manager_partial_bookings_month_view.html +++ b/chrono/manager/templates/chrono/manager_partial_bookings_month_view.html @@ -3,33 +3,54 @@ {% block content %} - - - - - +
+
+ + {% for day in days %} - + {% endfor %} - - + - - {% for booking_info in user_booking_info %} - - - {% for booking in booking_info.bookings %} - + + + + {% for day in days %} + {% endfor %} - {% endfor %} - + -
- {{ day|date:"d" }} -
{{ booking_info.user_name }} - {% if booking %} - - {% endif %} -
+ + + +
+ + {% for booking_info in user_booking_info %} + + {{ booking_info.user_name }} + {% for booking in booking_info.bookings %} + + {% if booking %} + {% if booking.check_css_class == 'present' %} + {% trans "Present" as booking_status %} + {% elif booking.check_css_class == 'absent' %} + {% trans "Absent" as booking_status %} + {% else %} + {% trans "Not checked" as booking_status %} + {% endif %} + + {{ booking_status }} + + {% endif %} + + {% endfor %} + + {% endfor %} + + + + {% endblock %} diff --git a/chrono/manager/views.py b/chrono/manager/views.py index ccf50490..eaa319fa 100644 --- a/chrono/manager/views.py +++ b/chrono/manager/views.py @@ -2268,6 +2268,7 @@ class AgendaWeekMonthMixin: self.first_day + datetime.timedelta(days=i) for i in range((first_day_next_month - self.first_day).days) ] + context['today'] = localtime().date() booking_info_by_user = {} bookings = Booking.objects.filter(event__in=self.events).prefetch_related('user_checks') diff --git a/tests/manager/test_partial_bookings.py b/tests/manager/test_partial_bookings.py index b8216f10..076c6e81 100644 --- a/tests/manager/test_partial_bookings.py +++ b/tests/manager/test_partial_bookings.py @@ -1138,7 +1138,7 @@ def test_manager_partial_bookings_month_view(app, admin_user, freezer): today = start_datetime.date() resp = app.get('/manage/agendas/%s/month/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day)) - assert [int(x.text) for x in resp.pyquery('thead th a')] == list(range(1, 32)) + assert [int(x.text) for x in resp.pyquery('thead th time')] == list(range(1, 32)) assert [x.text for x in resp.pyquery('tbody tr th')] == [ 'User Absent', @@ -1151,21 +1151,24 @@ def test_manager_partial_bookings_month_view(app, admin_user, freezer): user_absent_row = resp.pyquery('tbody tr')[0] assert len(resp.pyquery(user_absent_row)('td')) == 31 - assert len(resp.pyquery(user_absent_row)('td span')) == 1 + assert len(resp.pyquery(user_absent_row)('td span.booking')) == 1 assert len(resp.pyquery(user_absent_row)('td span.booking.absent')) == 1 + assert resp.pyquery(user_absent_row)('td span.booking.absent').text() == 'Absent' subscription_not_booked_row = resp.pyquery('tbody tr')[1] assert len(resp.pyquery(subscription_not_booked_row)('td')) == 31 - assert len(resp.pyquery(subscription_not_booked_row)('td span')) == 0 + assert len(resp.pyquery(subscription_not_booked_row)('td span.booking')) == 0 user_not_checked_row = resp.pyquery('tbody tr')[2] assert len(resp.pyquery(user_not_checked_row)('td')) == 31 assert len(resp.pyquery(user_not_checked_row)('td span.booking')) == 2 + assert resp.pyquery(user_not_checked_row)('td span.booking').text() == 'Not checked Not checked' user_present_row = resp.pyquery('tbody tr')[3] assert len(resp.pyquery(user_present_row)('td')) == 31 - assert len(resp.pyquery(user_present_row)('td span')) == 1 + assert len(resp.pyquery(user_present_row)('td span.booking')) == 1 assert len(resp.pyquery(user_present_row)('td span.booking.present')) == 1 + assert resp.pyquery(user_present_row)('td span.booking.present').text() == 'Present' user_present_mixed_row = resp.pyquery('tbody tr')[4] assert len(resp.pyquery(user_present_mixed_row)('td')) == 31 @@ -1178,10 +1181,20 @@ def test_manager_partial_bookings_month_view(app, admin_user, freezer): assert len(resp.pyquery(user_present_incomplete_row)('td span.booking.present')) == 0 resp = resp.click('Next month') - assert [int(x.text) for x in resp.pyquery('thead th a')] == list(range(1, 31)) + assert [int(x.text) for x in resp.pyquery('thead th time')] == list(range(1, 31)) assert [x.text for x in resp.pyquery('tbody tr th')] == ['Subscription Next Month'] assert len(resp.pyquery('tbody tr td')) == 30 + freezer.move_to('2023-05-10 14:00') + resp = app.get(resp.request.url) + assert len(resp.pyquery('th.today')) == 0 + assert len(resp.pyquery('col.today')) == 0 + + freezer.move_to('2023-06-10 14:00') + resp = app.get(resp.request.url) + assert resp.pyquery('th.today').text() == '10' + assert len(resp.pyquery('col.today')) == 1 + def test_manager_partial_bookings_occupation_rates(app, admin_user): agenda = Agenda.objects.create(label='Foo bar', kind='events', partial_bookings=True)