manager: display exceptions in day/month views (#39906)
This commit is contained in:
parent
3d9ea06ec7
commit
f6bb6282ac
|
@ -172,13 +172,17 @@ a.timeperiod-exception-all {
|
|||
padding: 1ex;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
&.opening-hours {
|
||||
&.opening-hours, &.exception-hours {
|
||||
z-index: 1;
|
||||
background: #b1ea4d linear-gradient(135deg, #b1ea4d 0%, #459522 100%);
|
||||
opacity: 0.6;
|
||||
left: 0.5ex;
|
||||
width: calc(100% - 1ex);
|
||||
}
|
||||
&.exception-hours {
|
||||
background: #fee linear-gradient(135deg, #fee 0%, #fdd 100%);
|
||||
text-align: center;
|
||||
}
|
||||
&.booking {
|
||||
background: #eef linear-gradient(135deg, #eef 0%, #ddf 100%);
|
||||
box-shadow: 0 0 1px 0 #2d2dad;
|
||||
|
|
|
@ -60,6 +60,11 @@
|
|||
style="height: {{ slot.css_height }}%; top: {{ slot.css_top }}%;"
|
||||
>{{slot.begin}} {{slot.end}}</div>
|
||||
{% endfor %}
|
||||
{% for slot in desk_info.exceptions %}
|
||||
<div class="exception-hours"
|
||||
style="height: {{ slot.css_height }}%; top: {{ slot.css_top }}%;"
|
||||
>{% if slot.label %}<span class="exception-label">{{slot.label}}</span>{% endif %}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% for booking in desk_info.bookings %}
|
||||
|
|
|
@ -26,6 +26,11 @@
|
|||
{% for slot in day.infos.opening_hours %}
|
||||
<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>
|
||||
{% endfor %}
|
||||
|
||||
{% for slot in day.infos.exceptions %}
|
||||
<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>
|
||||
{% endfor %}
|
||||
|
||||
{% for slot in day.infos.booked_slots %}
|
||||
<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" }}%">
|
||||
<span class="start-time">{{slot.booking.event.start_datetime|date:"TIME_FORMAT"}}</span>
|
||||
|
|
|
@ -380,7 +380,7 @@ class AgendaDayView(AgendaDateView, DayArchiveView):
|
|||
# until the end of the last hour.
|
||||
max_date += datetime.timedelta(hours=1)
|
||||
|
||||
desks = self.agenda.desk_set.all()
|
||||
desks = self.agenda.desk_set.all().prefetch_related('timeperiodexception_set')
|
||||
|
||||
first = True
|
||||
while current_date < max_date:
|
||||
|
@ -399,6 +399,20 @@ class AgendaDayView(AgendaDateView, DayArchiveView):
|
|||
'css_height': 100 * (opening_hour.end - opening_hour.begin).seconds // 3600,
|
||||
}
|
||||
)
|
||||
|
||||
# and exceptions for this desk
|
||||
info['exceptions'] = []
|
||||
for exception in desk.timeperiodexception_set.all():
|
||||
if exception.end_datetime < start_date:
|
||||
continue
|
||||
if exception.start_datetime > max_date:
|
||||
continue
|
||||
start_max = max(start_date, exception.start_datetime)
|
||||
end_min = min(max_date, exception.end_datetime)
|
||||
exception.css_top = int(100 * (start_max - start_date).seconds // 3600)
|
||||
exception.css_height = int(100 * (end_min - start_max).seconds // 3600)
|
||||
info['exceptions'].append(exception)
|
||||
|
||||
infos.append(info)
|
||||
info['bookings'] = bookings = [] # bookings for this desk
|
||||
finish_datetime = current_date + interval
|
||||
|
@ -511,10 +525,10 @@ class AgendaMonthView(AgendaDateView, MonthArchiveView):
|
|||
'date': current_date,
|
||||
'today': day.date() == datetime.date.today(),
|
||||
'other_month': day.month != self.date.month,
|
||||
'infos': {'opening_hours': [], 'booked_slots': []},
|
||||
'infos': {'opening_hours': [], 'exceptions': [], 'booked_slots': []},
|
||||
}
|
||||
|
||||
desks = self.agenda.desk_set.all()
|
||||
desks = self.agenda.desk_set.all().prefetch_related('timeperiodexception_set')
|
||||
desks_len = len(desks)
|
||||
max_date = day.replace(hour=self.max_timeperiod.hour, minute=0)
|
||||
|
||||
|
@ -557,6 +571,19 @@ class AgendaMonthView(AgendaDateView, MonthArchiveView):
|
|||
'css_left': left,
|
||||
}
|
||||
)
|
||||
for exception in desk.timeperiodexception_set.all():
|
||||
if exception.end_datetime < current_date:
|
||||
continue
|
||||
if exception.start_datetime > max_date:
|
||||
continue
|
||||
start_max = max(current_date, exception.start_datetime)
|
||||
end_min = min(max_date, exception.end_datetime)
|
||||
exception.css_top = int(100 * (start_max - current_date).seconds // 3600)
|
||||
exception.css_height = int(100 * (end_min - start_max).seconds // 3600)
|
||||
exception.css_width = width
|
||||
exception.css_left = left
|
||||
timetable['infos']['exceptions'].append(exception)
|
||||
|
||||
left += width + 1
|
||||
period += interval
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ from __future__ import unicode_literals
|
|||
import copy
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.utils.encoding import force_text
|
||||
|
@ -1724,6 +1725,23 @@ def test_agenda_day_view(app, admin_user, manager_user, api_user):
|
|||
agenda.save()
|
||||
resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200)
|
||||
|
||||
# display exception
|
||||
TimePeriodException.objects.create(
|
||||
label='Exception for the afternoon',
|
||||
desk=desk,
|
||||
start_datetime=make_aware(datetime.datetime(date.year, date.month, date.day, 13, 0)),
|
||||
end_datetime=make_aware(datetime.datetime(date.year, date.month, date.day, 23, 0)),
|
||||
)
|
||||
resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200)
|
||||
# day is displaying rows from 10am to 6pm,
|
||||
# opening hours, 10am to 1pm gives top: 300%
|
||||
# rest of the day, 1pm to 6(+1)pm gives 600%
|
||||
assert resp.pyquery.find('.exception-hours')[0].attrib == {
|
||||
'class': 'exception-hours',
|
||||
'style': 'height: 600%; top: 300%;',
|
||||
}
|
||||
assert resp.pyquery.find('.exception-hours span')[0].text == 'Exception for the afternoon'
|
||||
|
||||
|
||||
def test_agenda_day_view_late_meeting(app, admin_user, manager_user, api_user):
|
||||
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
||||
|
@ -1888,6 +1906,20 @@ def test_agenda_month_view(app, admin_user, manager_user, api_user):
|
|||
resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month))
|
||||
assert not 'No opening hours this month.' in resp.text
|
||||
|
||||
# display exception
|
||||
TimePeriodException.objects.create(
|
||||
label='Exception for a December day',
|
||||
desk=desk,
|
||||
start_datetime=make_aware(datetime.datetime(2018, 12, 15, 5, 0)),
|
||||
end_datetime=make_aware(datetime.datetime(2018, 12, 15, 23, 0)),
|
||||
)
|
||||
resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month))
|
||||
assert resp.pyquery.find('.exception-hours')[0].attrib == {
|
||||
'class': 'exception-hours',
|
||||
'style': 'height:800.0%;top:0.0%;width:48.0%;left:50.0%;',
|
||||
'title': 'Exception for a December day',
|
||||
}
|
||||
|
||||
|
||||
def test_agenda_month_view_weekend(app, admin_user, manager_user, api_user):
|
||||
agenda = Agenda.objects.create(label='Passeports', kind='meetings')
|
||||
|
|
Loading…
Reference in New Issue