Swap the axes in the meeting schedule editor and rework it to allow
flowing the days. Add JS workaround for missing position sticky support, instead of the CSS workaround which added an annoying padding for everyone. - Legacy-Id: 17616
This commit is contained in:
parent
b8b1b67e6d
commit
6c48575042
|
@ -508,17 +508,14 @@ def edit_meeting_schedule(request, num=None, owner=None, name=None):
|
|||
for a in assignments:
|
||||
assignments_by_session[a.session_id].append(a)
|
||||
|
||||
# Prepare timeslot layout. We arrange time slots in columns per
|
||||
# room where everything inside is grouped by day. Things inside
|
||||
# the days are then layouted proportionally to the actual time of
|
||||
# day, to ensure that everything lines up, even if the time slots
|
||||
# are not the same in the different rooms.
|
||||
# Prepare timeslot layout, making a timeline per day scaled in
|
||||
# browser em units to ensure that everything lines up even if the
|
||||
# timeslots are not the same in the different rooms
|
||||
|
||||
def timedelta_to_css_ems(timedelta):
|
||||
css_ems_per_hour = 1.8
|
||||
css_ems_per_hour = 5
|
||||
return timedelta.seconds / 60.0 / 60.0 * css_ems_per_hour
|
||||
|
||||
# time labels column
|
||||
timeslots_by_day = defaultdict(list)
|
||||
for t in timeslots_qs:
|
||||
timeslots_by_day[t.time.date()].append(t)
|
||||
|
@ -526,10 +523,19 @@ def edit_meeting_schedule(request, num=None, owner=None, name=None):
|
|||
day_min_max = []
|
||||
for day, timeslots in sorted(timeslots_by_day.iteritems()):
|
||||
day_min_max.append((day, min(t.time for t in timeslots), max(t.end_time() for t in timeslots)))
|
||||
|
||||
time_labels = []
|
||||
|
||||
timeslots_by_room_and_day = defaultdict(list)
|
||||
room_has_timeslots = set()
|
||||
for t in timeslots_qs:
|
||||
room_has_timeslots.add(t.location_id)
|
||||
timeslots_by_room_and_day[(t.location_id, t.time.date())].append(t)
|
||||
|
||||
days = []
|
||||
for day, day_min_time, day_max_time in day_min_max:
|
||||
day_labels = []
|
||||
day_width = timedelta_to_css_ems(day_max_time - day_min_time)
|
||||
|
||||
label_width = 4 # em
|
||||
|
||||
hourly_delta = 2
|
||||
|
||||
|
@ -540,47 +546,42 @@ def edit_meeting_schedule(request, num=None, owner=None, name=None):
|
|||
end = day_max_time.replace(hour=last_hour, minute=0, second=0, microsecond=0)
|
||||
|
||||
while t <= end:
|
||||
day_labels.append((t, 'top', timedelta_to_css_ems(t - day_min_time), 'left'))
|
||||
left_offset = timedelta_to_css_ems(t - day_min_time)
|
||||
right_offset = day_width - left_offset
|
||||
if right_offset > label_width:
|
||||
# there's room for the label
|
||||
day_labels.append((t, 'left', left_offset))
|
||||
else:
|
||||
day_labels.append((t, 'right', right_offset))
|
||||
|
||||
t += datetime.timedelta(seconds=hourly_delta * 60 * 60)
|
||||
|
||||
if not day_labels:
|
||||
day_labels.append((day_min_time, 'top', 0, 'left'))
|
||||
day_labels.append((day_min_time, 'left', 0))
|
||||
|
||||
time_labels.append({
|
||||
'day': day,
|
||||
'height': timedelta_to_css_ems(day_max_time - day_min_time),
|
||||
'labels': day_labels,
|
||||
})
|
||||
room_timeslots = []
|
||||
for r in rooms:
|
||||
if r.pk not in room_has_timeslots:
|
||||
continue
|
||||
|
||||
# room columns
|
||||
timeslots_by_room_and_day = defaultdict(list)
|
||||
for t in timeslots_qs:
|
||||
timeslots_by_room_and_day[(t.location_id, t.time.date())].append(t)
|
||||
|
||||
room_columns = []
|
||||
for r in rooms:
|
||||
room_days = []
|
||||
|
||||
for day, day_min_time, day_max_time in day_min_max:
|
||||
day_timeslots = []
|
||||
timeslots = []
|
||||
for t in timeslots_by_room_and_day.get((r.pk, day), []):
|
||||
day_timeslots.append({
|
||||
timeslots.append({
|
||||
'timeslot': t,
|
||||
'offset': timedelta_to_css_ems(t.time - day_min_time),
|
||||
'height': timedelta_to_css_ems(t.end_time() - t.time),
|
||||
'width': timedelta_to_css_ems(t.end_time() - t.time),
|
||||
})
|
||||
|
||||
room_days.append({
|
||||
'day': day,
|
||||
'timeslots': day_timeslots,
|
||||
'height': timedelta_to_css_ems(day_max_time - day_min_time),
|
||||
})
|
||||
room_timeslots.append((r, timeslots))
|
||||
|
||||
if any(d['timeslots'] for d in room_days):
|
||||
room_columns.append({
|
||||
'room': r,
|
||||
'days': room_days,
|
||||
})
|
||||
days.append({
|
||||
'day': day,
|
||||
'width': day_width,
|
||||
'time_labels': day_labels,
|
||||
'room_timeslots': room_timeslots,
|
||||
})
|
||||
|
||||
room_labels = [[r for r in rooms if r.pk in room_has_timeslots] for i in range(len(days))]
|
||||
|
||||
# prepare sessions
|
||||
for ts in timeslots_qs:
|
||||
|
@ -701,7 +702,7 @@ def edit_meeting_schedule(request, num=None, owner=None, name=None):
|
|||
s.requested_duration_in_hours = s.requested_duration.seconds / 60.0 / 60.0
|
||||
|
||||
session_layout_margin = 0.2
|
||||
s.layout_height = timedelta_to_css_ems(s.requested_duration) - 2 * session_layout_margin
|
||||
s.layout_width = timedelta_to_css_ems(s.requested_duration) - 2 * session_layout_margin
|
||||
s.parent_acronym = s.group.parent.acronym if s.group and s.group.parent else ""
|
||||
s.historic_group_ad_name = ad_names.get(s.group_id)
|
||||
|
||||
|
@ -744,9 +745,8 @@ def edit_meeting_schedule(request, num=None, owner=None, name=None):
|
|||
'schedule': schedule,
|
||||
'can_edit': can_edit,
|
||||
'js_data': json.dumps(js_data, indent=2),
|
||||
'time_labels': time_labels,
|
||||
'rooms': rooms,
|
||||
'room_columns': room_columns,
|
||||
'days': days,
|
||||
'room_labels': room_labels,
|
||||
'unassigned_sessions': unassigned_sessions,
|
||||
'session_parents': session_parents,
|
||||
'hide_menu': True,
|
||||
|
|
|
@ -974,7 +974,7 @@ a.fc-event, .fc-event, .fc-content, .fc-title, .fc-event-container {
|
|||
|
||||
.fc-button {
|
||||
/* same as button-primary */
|
||||
background-image: linear-gradient(rgb(107, 91, 173) 0px, rgb(80, 68, 135) 100%)
|
||||
background-image: linear-gradient(rgb(107, 91, 173) 0px, rgb(80, 68, 135) 100%);
|
||||
}
|
||||
|
||||
/* === Edit Milestones============================================= */
|
||||
|
@ -987,62 +987,77 @@ a.fc-event, .fc-event, .fc-content, .fc-title, .fc-event-container {
|
|||
/* === Edit Meeting Schedule ====================================== */
|
||||
|
||||
.edit-meeting-schedule .edit-grid {
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .schedule-column .room-name {
|
||||
height: 2em;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
.edit-meeting-schedule .edit-grid .room-label-column {
|
||||
/* make sure we cut this column off - the time slots will determine
|
||||
how much of it is shown */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
width: 8em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .schedule-column .day-label {
|
||||
height: 2.5em;
|
||||
max-width: 5em; /* let it stick out and overlap the other columns */
|
||||
white-space: nowrap;
|
||||
font-style: italic;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .schedule-column > .day {
|
||||
position: relative;
|
||||
.edit-meeting-schedule .edit-grid .day {
|
||||
margin-right: 2.5em;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .schedule-column > .day > div {
|
||||
.edit-meeting-schedule .edit-grid .day-label {
|
||||
height: 3em;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .edit-grid .day-flow {
|
||||
margin-left: 8em;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .edit-grid .day-flow .day-label {
|
||||
border-bottom: 2px solid #eee;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .edit-grid .timeline {
|
||||
position: relative;
|
||||
height: 1.6em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .edit-grid .timeline > div {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .time-labels-column > div {
|
||||
min-width: 5em;
|
||||
padding-right: 0.5em;
|
||||
.edit-meeting-schedule .edit-grid .timeline.timeslots {
|
||||
height: 3.3em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .time-labels-column .time-label.top-aligned {
|
||||
border-top: 1px solid #ccc;
|
||||
.edit-meeting-schedule .edit-grid .timeline .time-label {
|
||||
font-size: smaller;
|
||||
border-left: 2px solid #eee;
|
||||
border-right: 2px solid #eee;
|
||||
padding: 0 0.2em;
|
||||
height: 1.3em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .time-labels-column .time-label.text-left span {
|
||||
background-color: #fff;
|
||||
padding-right: 0.2em;
|
||||
.edit-meeting-schedule .edit-grid .timeline .time-label.text-left {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .time-labels-column .time-label.bottom-aligned {
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .room-column {
|
||||
flex-grow: 1;
|
||||
.edit-meeting-schedule .edit-grid .timeline .time-label.text-right {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .timeslot {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
background-color: #eee;
|
||||
width: 100%;
|
||||
border-left: 0.15em solid #fff;
|
||||
height: 100%;
|
||||
border-bottom: 0.15em solid #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
@ -1052,99 +1067,23 @@ a.fc-event, .fc-event, .fc-content, .fc-title, .fc-event-container {
|
|||
}
|
||||
|
||||
.edit-meeting-schedule .timeslot.overfull {
|
||||
border-bottom: 2px dashed #fff; /* cut-off illusion */
|
||||
}
|
||||
|
||||
.edit-meeting-schedule {
|
||||
/* this is backwards-compatible measure - if the browser doesn't
|
||||
support position: sticky but only position: fixed, we ensure there's room for the scheduling
|
||||
panel */
|
||||
padding-bottom: 5em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .scheduling-panel {
|
||||
position: fixed; /* backwards compatibility */
|
||||
z-index: 1;
|
||||
|
||||
position: sticky;
|
||||
display: flex;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
border-top: 0.2em solid #ccc;
|
||||
background-color: #fff;
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .scheduling-panel .unassigned-container {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .unassigned-sessions {
|
||||
min-height: 4em;
|
||||
max-height: 13em;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
background-color: #eee;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .unassigned-sessions.dropping {
|
||||
background-color: #e5e5e5;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .scheduling-panel .preferences {
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .scheduling-panel .preferences > span {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .sort-unassigned select {
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .session-parent-toggles {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .session-parent-toggles label {
|
||||
font-weight: normal;
|
||||
margin-right: 1em;
|
||||
padding: 0 1em;
|
||||
border: 0.1em solid #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .scheduling-panel .session-info-container {
|
||||
padding-left: 0.5em;
|
||||
flex: 0 0 20em;
|
||||
max-height: 15em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .scheduling-panel .session-info-container .comments {
|
||||
font-style: italic;
|
||||
border-right: 2px dashed #fff; /* cut-off illusion */
|
||||
}
|
||||
|
||||
/* sessions */
|
||||
.edit-meeting-schedule .session {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
padding: 0 0.2em;
|
||||
padding-left: 0.5em;
|
||||
margin: 0.2em;
|
||||
padding-right: 0.2em;
|
||||
padding-left: 0.5em;
|
||||
line-height: 1.3em;
|
||||
border-radius: 0.4em;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .session.selected {
|
||||
border: 1px solid #bbb;
|
||||
background-color: #fcfcfc;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .session.dragging {
|
||||
|
@ -1153,13 +1092,8 @@ a.fc-event, .fc-event, .fc-content, .fc-title, .fc-event-container {
|
|||
}
|
||||
|
||||
.edit-meeting-schedule .timeslot.overfull .session {
|
||||
border-radius: 0.4em 0.4em 0 0; /* remove bottom rounding to illude to being cut off */
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .unassigned-sessions .session {
|
||||
min-width: 6em;
|
||||
margin-right: 0.3em;
|
||||
border-radius: 0.4em 0 0 0.4em; /* remove bottom rounding to illude to being cut off */
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .session .session-label {
|
||||
|
@ -1208,12 +1142,75 @@ a.fc-event, .fc-event, .fc-content, .fc-title, .fc-event-container {
|
|||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.edit-meeting-schedule .session .comments {
|
||||
font-size: smaller;
|
||||
margin-right: 0.1em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .session .session-info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* scheduling panel */
|
||||
.edit-meeting-schedule .scheduling-panel {
|
||||
position: sticky;
|
||||
display: flex;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
border-top: 0.2em solid #ccc;
|
||||
background-color: #fff;
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .scheduling-panel .unassigned-container {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .unassigned-sessions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
margin-top: 0.5em;
|
||||
min-height: 4em;
|
||||
max-height: 13em;
|
||||
overflow-y: auto;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .unassigned-sessions.dropping {
|
||||
background-color: #e5e5e5;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .scheduling-panel .preferences {
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .scheduling-panel .preferences > span {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .sort-unassigned select {
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .session-parent-toggles {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .session-parent-toggles label {
|
||||
font-weight: normal;
|
||||
margin-right: 1em;
|
||||
padding: 0 1em;
|
||||
border: 0.1em solid #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .scheduling-panel .session-info-container {
|
||||
padding-left: 0.5em;
|
||||
flex: 0 0 20em;
|
||||
max-height: 15em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.edit-meeting-schedule .scheduling-panel .session-info-container .comments {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,12 @@ jQuery(document).ready(function () {
|
|||
let sessions = content.find(".session");
|
||||
let timeslots = content.find(".timeslot");
|
||||
|
||||
// hack to work around lack of position sticky support in old browsers, see https://caniuse.com/#feat=css-sticky
|
||||
if (content.find(".scheduling-panel").css("position") != "sticky") {
|
||||
content.find(".scheduling-panel").css("position", "fixed");
|
||||
content.css("padding-bottom", "14em");
|
||||
}
|
||||
|
||||
// selecting
|
||||
function selectSessionElement(element) {
|
||||
if (element) {
|
||||
|
@ -220,7 +226,7 @@ jQuery(document).ready(function () {
|
|||
|
||||
function updateAttendeesViolations() {
|
||||
sessions.each(function () {
|
||||
let roomCapacity = jQuery(this).closest(".room-column").data("roomcapacity");
|
||||
let roomCapacity = jQuery(this).closest(".timeline").data("roomcapacity");
|
||||
if (roomCapacity && this.dataset.attendees)
|
||||
jQuery(this).toggleClass("too-many-attendees", +this.dataset.attendees > +roomCapacity);
|
||||
});
|
||||
|
|
|
@ -48,43 +48,59 @@
|
|||
</p>
|
||||
|
||||
<div class="edit-grid">
|
||||
{# in order for all this to align properly vertically, we have the same structure in all columns #}
|
||||
|
||||
<div class="time-labels-column schedule-column">
|
||||
<div class="room-name"></div>
|
||||
{# using the same markup in both room labels and the actual days ensures they are aligned #}
|
||||
<div class="room-label-column">
|
||||
{% for labels in room_labels %}
|
||||
<div class="day">
|
||||
<div class="day-label">
|
||||
<strong> </strong><br>
|
||||
|
||||
</div>
|
||||
|
||||
{% for d in time_labels %}
|
||||
<div class="day-label">{{ d.day|date:"l, F j, Y" }}</div>
|
||||
<div class="timeline"></div>
|
||||
|
||||
<div class="day" style="height: {{ d.height }}em;">
|
||||
{% for t, vertical_alignment, vertical_offset, horizontal_alignment in d.labels %}
|
||||
<div class="time-label {{ vertical_alignment }}-aligned text-{{ horizontal_alignment }}" style="{{ vertical_alignment }}: {{ vertical_offset }}em;">
|
||||
<span>{{ t|date:"H:i" }}</span>
|
||||
{% for room in labels %}
|
||||
<div class="timeline timeslots">
|
||||
<div class="room-name">
|
||||
<strong>{{ room.name }}</strong><br>
|
||||
{% if room.capacity %}{{ room.capacity }} <i class="fa fa-user-o"></i>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% for r in room_columns %}
|
||||
<div class="room-column schedule-column" data-roomcapacity="{{ r.room.capacity }}">
|
||||
<div class="room-name">{{ r.room.name }}{% if r.room.capacity %} ({{ r.room.capacity }} <i class="fa fa-user-o"></i>{% endif %})</div>
|
||||
<div class="day-flow">
|
||||
{% for day in days %}
|
||||
<div class="day" style="width: {{ day.width }}em;">
|
||||
<div class="day-label">
|
||||
<strong>{{ day.day|date:"l" }}</strong><br>
|
||||
{{ day.day|date:"N j, Y" }}
|
||||
</div>
|
||||
|
||||
{% for d in r.days %}
|
||||
<div class="day-label"></div> {# for spacing purposes #}
|
||||
|
||||
<div class="day" style="height: {{ d.height }}em;">
|
||||
{% for t in d.timeslots %}
|
||||
<div id="timeslot{{ t.timeslot.pk }}" class="timeslot" data-start="{{ t.timeslot.time.isoformat }}" data-end="{{ t.timeslot.end_time.isoformat }}" data-duration="{{ t.timeslot.duration.total_seconds }}" style="top: {{ t.offset }}em; height: {{ t.height }}em;">
|
||||
{% for assignment, session in t.timeslot.session_assignments %}
|
||||
{% include "meeting/edit_meeting_schedule_session.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="timeline">
|
||||
{% for t, left_or_right, offset in day.time_labels %}
|
||||
<div class="time-label text-{{ left_or_right }}" style="{{ left_or_right }}: {{ offset }}em;">{{ t|date:"H:i" }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% for room, timeslots in day.room_timeslots %}
|
||||
<div class="timeline timeslots" data-roomcapacity="{{ room.capacity }}">
|
||||
|
||||
{% for t in timeslots %}
|
||||
<div id="timeslot{{ t.timeslot.pk }}" class="timeslot" data-start="{{ t.timeslot.time.isoformat }}" data-end="{{ t.timeslot.end_time.isoformat }}" data-duration="{{ t.timeslot.duration.total_seconds }}" style="left: {{ t.offset }}em; width: {{ t.width }}em;">
|
||||
{% for assignment, session in t.timeslot.session_assignments %}
|
||||
{% include "meeting/edit_meeting_schedule_session.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="scheduling-panel">
|
||||
|
|
|
@ -1,25 +1,27 @@
|
|||
<div id="session{{ session.pk }}" class="session {% if not session.group.parent.scheduling_color %}untoggleable{% endif %} {% if session.parent_acronym %}parent-{{ session.parent_acronym }}{% endif %}" style="height:{{ session.layout_height }}em;" data-duration="{{ session.requested_duration.total_seconds }}" {% if session.attendees != None %}data-attendees="{{ session.attendees }}"{% endif %}>
|
||||
<div id="session{{ session.pk }}" class="session {% if not session.group.parent.scheduling_color %}untoggleable{% endif %} {% if session.parent_acronym %}parent-{{ session.parent_acronym }}{% endif %}" style="width:{{ session.layout_width }}em;" data-duration="{{ session.requested_duration.total_seconds }}" {% if session.attendees != None %}data-attendees="{{ session.attendees }}"{% endif %}>
|
||||
<div class="session-label">
|
||||
{{ session.scheduling_label }}
|
||||
</div>
|
||||
|
||||
{% if session.constrained_sessions %}
|
||||
<div class="constraints">
|
||||
{% for explanation, sessions in session.constrained_sessions %}
|
||||
<span data-sessions="{{ sessions|join:"," }}">{{ explanation }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
{% if session.attendees != None %}
|
||||
<span class="attendees">{{ session.attendees }}</span>
|
||||
{% endif %}
|
||||
|
||||
{% if session.comments %}
|
||||
<div class="comments"><i class="fa fa-comment-o"></i></div>
|
||||
{% endif %}
|
||||
|
||||
{% if session.attendees != None %}
|
||||
<div class="attendees">{{ session.attendees }}</div>
|
||||
{% endif %}
|
||||
{% if session.comments %}
|
||||
<span class="comments"><i class="fa fa-comment-o"></i></span>
|
||||
{% endif %}
|
||||
|
||||
{% if session.constrained_sessions %}
|
||||
<span class="constraints">
|
||||
{% for explanation, sessions in session.constrained_sessions %}
|
||||
<span data-sessions="{{ sessions|join:"," }}">{{ explanation }}</span>
|
||||
{% endfor %}
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{# this is shown elsewhere on the page with JS - we just include it here for convenience #}
|
||||
<div class="session-info">
|
||||
<label>
|
||||
{{ session.scheduling_label }}
|
||||
|
|
Loading…
Reference in a new issue