Projet

Général

Profil

0001-manager-display-exceptions-in-day-month-views-39906.patch

Frédéric Péters, 04 mars 2020 16:29

Télécharger (9,41 ko)

Voir les différences:

Subject: [PATCH] manager: display exceptions in day/month views (#39906)

 chrono/manager/static/css/style.scss          |  6 +++-
 .../chrono/manager_agenda_day_view.html       |  5 +++
 .../manager_meetings_agenda_month_view.html   |  5 +++
 chrono/manager/views.py                       | 33 +++++++++++++++++--
 tests/test_manager.py                         | 32 ++++++++++++++++++
 5 files changed, 77 insertions(+), 4 deletions(-)
chrono/manager/static/css/style.scss
172 172
	padding: 1ex;
173 173
	position: absolute;
174 174
	overflow: hidden;
175
	&.opening-hours {
175
	&.opening-hours, &.exception-hours {
176 176
		z-index: 1;
177 177
		background: #b1ea4d linear-gradient(135deg, #b1ea4d 0%, #459522 100%);
178 178
		opacity: 0.6;
179 179
		left: 0.5ex;
180 180
		width: calc(100% - 1ex);
181 181
	}
182
	&.exception-hours {
183
		background: #fee linear-gradient(135deg, #fee 0%, #fdd 100%);
184
		text-align: center;
185
	}
182 186
	&.booking {
183 187
		background: #eef linear-gradient(135deg, #eef 0%, #ddf 100%);
184 188
		box-shadow: 0 0 1px 0 #2d2dad;
chrono/manager/templates/chrono/manager_agenda_day_view.html
60 60
               style="height: {{ slot.css_height }}%; top: {{ slot.css_top }}%;"
61 61
                  >{{slot.begin}} {{slot.end}}</div>
62 62
          {% endfor %}
63
          {% for slot in desk_info.exceptions %}
64
          <div class="exception-hours"
65
               style="height: {{ slot.css_height }}%; top: {{ slot.css_top }}%;"
66
               >{% if slot.label %}<span class="exception-label">{{slot.label}}</span>{% endif %}</div>
67
          {% endfor %}
63 68
        {% endif %}
64 69

  
65 70
        {% for booking in desk_info.bookings %}
chrono/manager/templates/chrono/manager_meetings_agenda_month_view.html
26 26
      {% for slot in day.infos.opening_hours %}
27 27
      <div class="opening-hours" style="height:{{ slot.css_height|stringformat:".1f" }}%;top:{{ slot.css_top|stringformat:".1f" }}%;width:{{ slot.css_width|stringformat:".1f" }}%;left:{{ slot.css_left|stringformat:".1f" }}%;"></div>
28 28
      {% endfor %}
29

  
30
      {% for slot in day.infos.exceptions %}
31
      <div class="exception-hours" style="height:{{ slot.css_height|stringformat:".1f" }}%;top:{{ slot.css_top|stringformat:".1f" }}%;width:{{ slot.css_width|stringformat:".1f" }}%;left:{{ slot.css_left|stringformat:".1f" }}%;" {% if slot.label %}title="{{ slot.label }}"{% endif %}></div>
32
      {% endfor %}
33

  
29 34
      {% for slot in day.infos.booked_slots %}
30 35
      <div class="booking" style="left:{{ slot.css_left|stringformat:".1f" }}%;height:{{ slot.css_height|stringformat:".1f" }}%;top:{{ slot.css_top|stringformat:".1f" }}%;width:{{ slot.css_width|stringformat:".1f" }}%">
31 36
        <span class="start-time">{{slot.booking.event.start_datetime|date:"TIME_FORMAT"}}</span>
chrono/manager/views.py
380 380
            # until the end of the last hour.
381 381
            max_date += datetime.timedelta(hours=1)
382 382

  
383
        desks = self.agenda.desk_set.all()
383
        desks = self.agenda.desk_set.all().prefetch_related('timeperiodexception_set')
384 384

  
385 385
        first = True
386 386
        while current_date < max_date:
......
399 399
                                'css_height': 100 * (opening_hour.end - opening_hour.begin).seconds // 3600,
400 400
                            }
401 401
                        )
402

  
403
                    # and exceptions for this desk
404
                    info['exceptions'] = []
405
                    for exception in desk.timeperiodexception_set.all():
406
                        if exception.end_datetime < start_date:
407
                            continue
408
                        if exception.start_datetime > max_date:
409
                            continue
410
                        start_max = max(start_date, exception.start_datetime)
411
                        end_min = min(max_date, exception.end_datetime)
412
                        exception.css_top = int(100 * (start_max - start_date).seconds // 3600)
413
                        exception.css_height = int(100 * (end_min - start_max).seconds // 3600)
414
                        info['exceptions'].append(exception)
415

  
402 416
                infos.append(info)
403 417
                info['bookings'] = bookings = []  # bookings for this desk
404 418
                finish_datetime = current_date + interval
......
511 525
            'date': current_date,
512 526
            'today': day.date() == datetime.date.today(),
513 527
            'other_month': day.month != self.date.month,
514
            'infos': {'opening_hours': [], 'booked_slots': []},
528
            'infos': {'opening_hours': [], 'exceptions': [], 'booked_slots': []},
515 529
        }
516 530

  
517
        desks = self.agenda.desk_set.all()
531
        desks = self.agenda.desk_set.all().prefetch_related('timeperiodexception_set')
518 532
        desks_len = len(desks)
519 533
        max_date = day.replace(hour=self.max_timeperiod.hour, minute=0)
520 534

  
......
557 571
                                'css_left': left,
558 572
                            }
559 573
                        )
574
                    for exception in desk.timeperiodexception_set.all():
575
                        if exception.end_datetime < current_date:
576
                            continue
577
                        if exception.start_datetime > max_date:
578
                            continue
579
                        start_max = max(current_date, exception.start_datetime)
580
                        end_min = min(max_date, exception.end_datetime)
581
                        exception.css_top = int(100 * (start_max - current_date).seconds // 3600)
582
                        exception.css_height = int(100 * (end_min - start_max).seconds // 3600)
583
                        exception.css_width = width
584
                        exception.css_left = left
585
                        timetable['infos']['exceptions'].append(exception)
586

  
560 587
                left += width + 1
561 588
            period += interval
562 589

  
tests/test_manager.py
4 4
import copy
5 5
import json
6 6
import os
7
import re
7 8

  
8 9
from django.contrib.auth.models import User, Group
9 10
from django.utils.encoding import force_text
......
1724 1725
    agenda.save()
1725 1726
    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200)
1726 1727

  
1728
    # display exception
1729
    TimePeriodException.objects.create(
1730
        label='Exception for the afternoon',
1731
        desk=desk,
1732
        start_datetime=make_aware(datetime.datetime(date.year, date.month, date.day, 13, 0)),
1733
        end_datetime=make_aware(datetime.datetime(date.year, date.month, date.day, 23, 0)),
1734
    )
1735
    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200)
1736
    # day is displaying rows from 10am to 6pm,
1737
    # opening hours, 10am to 1pm gives top: 300%
1738
    # rest of the day, 1pm to 6(+1)pm gives 600%
1739
    assert resp.pyquery.find('.exception-hours')[0].attrib == {
1740
        'class': 'exception-hours',
1741
        'style': 'height: 600%; top: 300%;',
1742
    }
1743
    assert resp.pyquery.find('.exception-hours span')[0].text == 'Exception for the afternoon'
1744

  
1727 1745

  
1728 1746
def test_agenda_day_view_late_meeting(app, admin_user, manager_user, api_user):
1729 1747
    agenda = Agenda.objects.create(label='New Example', kind='meetings')
......
1888 1906
    resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month))
1889 1907
    assert not 'No opening hours this month.' in resp.text
1890 1908

  
1909
    # display exception
1910
    TimePeriodException.objects.create(
1911
        label='Exception for a December day',
1912
        desk=desk,
1913
        start_datetime=make_aware(datetime.datetime(2018, 12, 15, 5, 0)),
1914
        end_datetime=make_aware(datetime.datetime(2018, 12, 15, 23, 0)),
1915
    )
1916
    resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month))
1917
    assert resp.pyquery.find('.exception-hours')[0].attrib == {
1918
        'class': 'exception-hours',
1919
        'style': 'height:800.0%;top:0.0%;width:48.0%;left:50.0%;',
1920
        'title': 'Exception for a December day',
1921
    }
1922

  
1891 1923

  
1892 1924
def test_agenda_month_view_weekend(app, admin_user, manager_user, api_user):
1893 1925
    agenda = Agenda.objects.create(label='Passeports', kind='meetings')
1894
-