Skip to content

Commit 770341f

Browse files
committed
Add information about other sessions of the same group to the session
info in the new meeting schedule editor. - Legacy-Id: 18018
1 parent 674dae2 commit 770341f

6 files changed

Lines changed: 84 additions & 21 deletions

File tree

ietf/meeting/tests_js.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ def test_edit_meeting_schedule(self):
9797
s2.save()
9898
SchedTimeSessAssignment.objects.filter(session=s1).delete()
9999

100+
s2_b = Session.objects.create(meeting=meeting, group=s2.group, attendees=10, requested_duration=datetime.timedelta(minutes=60), type_id='regular')
101+
100102
Constraint.objects.create(
101103
meeting=meeting,
102104
source=s1.group,
@@ -109,17 +111,18 @@ def test_edit_meeting_schedule(self):
109111
self.driver.get(url)
110112

111113
q = PyQuery(self.driver.page_source)
112-
self.assertEqual(len(q('.session')), 2)
114+
self.assertEqual(len(q('.session')), 3)
113115

114116
# select - show session info
115117
s2_element = self.driver.find_element_by_css_selector('#session{}'.format(s2.pk))
116118
s2_element.click()
117119

118-
session_info_element = self.driver.find_element_by_css_selector('.session-info-container .title')
119-
self.assertIn(s2.group.acronym, session_info_element.text)
120+
session_info_container = self.driver.find_element_by_css_selector('.session-info-container')
121+
self.assertIn(s2.group.acronym, session_info_container.find_element_by_css_selector(".title").text)
122+
self.assertEqual(session_info_container.find_element_by_css_selector(".other-session .time").text, "not yet scheduled")
120123

121124
# deselect
122-
self.driver.find_element_by_css_selector('.session-info-container').click()
125+
self.driver.find_element_by_css_selector('.scheduling-panel').click()
123126

124127
self.assertEqual(self.driver.find_elements_by_css_selector('.session-info-container .title'), [])
125128

@@ -147,19 +150,19 @@ def test_edit_meeting_schedule(self):
147150
self.assertEqual(list(SchedTimeSessAssignment.objects.filter(session=s2, schedule=schedule)), [])
148151

149152
# sorting unassigned
150-
sorted_pks = [s.pk for s in sorted([s1, s2], key=lambda s: s.group.acronym)]
153+
sorted_pks = [s.pk for s in sorted([s1, s2, s2_b], key=lambda s: (s.group.acronym, s.requested_duration, s.pk))]
151154
self.driver.find_element_by_css_selector('[name=sort_unassigned] option[value=name]').click()
152-
self.assertTrue(self.driver.find_element_by_css_selector('.unassigned-sessions .drop-target #session{} + #session{}'.format(*sorted_pks)))
155+
self.assertTrue(self.driver.find_element_by_css_selector('.unassigned-sessions .drop-target #session{} + #session{} + #session{}'.format(*sorted_pks)))
153156

154-
sorted_pks = [s.pk for s in sorted([s1, s2], key=lambda s: (s.group.parent.acronym, s.group.acronym))]
157+
sorted_pks = [s.pk for s in sorted([s1, s2, s2_b], key=lambda s: (s.group.parent.acronym, s.group.acronym, s.requested_duration, s.pk))]
155158
self.driver.find_element_by_css_selector('[name=sort_unassigned] option[value=parent]').click()
156159
self.assertTrue(self.driver.find_element_by_css_selector('.unassigned-sessions .drop-target #session{} + #session{}'.format(*sorted_pks)))
157160

158-
sorted_pks = [s.pk for s in sorted([s1, s2], key=lambda s: (s.requested_duration, s.group.parent.acronym, s.group.acronym))]
161+
sorted_pks = [s.pk for s in sorted([s1, s2, s2_b], key=lambda s: (s.requested_duration, s.group.parent.acronym, s.group.acronym, s.pk))]
159162
self.driver.find_element_by_css_selector('[name=sort_unassigned] option[value=duration]').click()
160163
self.assertTrue(self.driver.find_element_by_css_selector('.unassigned-sessions .drop-target #session{} + #session{}'.format(*sorted_pks)))
161164

162-
sorted_pks = [s.pk for s in sorted([s1, s2], key=lambda s: (bool(s.comments), s.group.parent.acronym, s.group.acronym))]
165+
sorted_pks = [s.pk for s in sorted([s1, s2, s2_b], key=lambda s: (int(bool(s.comments)), s.group.parent.acronym, s.group.acronym, s.requested_duration, s.pk))]
163166
self.driver.find_element_by_css_selector('[name=sort_unassigned] option[value=comments]').click()
164167
self.assertTrue(self.driver.find_element_by_css_selector('.unassigned-sessions .drop-target #session{} + #session{}'.format(*sorted_pks)))
165168

@@ -204,6 +207,16 @@ def test_edit_meeting_schedule(self):
204207
self.assertTrue(s1_element.is_displayed())
205208
self.driver.find_element_by_css_selector(".session-parent-toggles [value=\"{}\"]".format(s1.group.parent.acronym)).click()
206209
self.assertTrue(not s1_element.is_displayed())
210+
self.driver.find_element_by_css_selector(".session-parent-toggles [value=\"{}\"]".format(s1.group.parent.acronym)).click()
211+
self.assertTrue(s1_element.is_displayed())
212+
213+
# hide timeslots
214+
self.driver.find_element_by_css_selector(".timeslot-group-toggles button".format(s1.group.parent.acronym)).click()
215+
self.assertTrue(self.driver.find_element_by_css_selector("#timeslot-group-toggles-modal").is_displayed())
216+
self.driver.find_element_by_css_selector("#timeslot-group-toggles-modal [value=\"{}\"]".format("ts-group-{}-{}".format(slot2.time.strftime("%Y%m%d-%H%M"), int(slot2.duration.total_seconds() / 60)))).click()
217+
self.driver.find_element_by_css_selector("#timeslot-group-toggles-modal [data-dismiss=\"modal\"]").click()
218+
self.assertTrue(not self.driver.find_element_by_css_selector("#timeslot-group-toggles-modal").is_displayed())
219+
207220

208221
@skipIf(skip_selenium, skip_message)
209222
@skipIf(django.VERSION[0]==2, "Skipping test with race conditions under Django 2")

ietf/meeting/views.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ def edit_meeting_schedule(request, num=None, owner=None, name=None):
466466
meeting=meeting,
467467
# Restrict graphical scheduling to regular meeting requests (Sessions) for now
468468
type='regular',
469-
),
469+
).order_by('pk'),
470470
requested_time=True,
471471
requested_by=True,
472472
).exclude(current_status__in=['notmeet', 'disappr', 'deleted', 'apprw']).prefetch_related(
@@ -603,6 +603,10 @@ def cubehelix(i, total, hue=1.2, start_angle=0.5):
603603
# constraints
604604
constraints_for_sessions, formatted_constraints_for_sessions, constraint_names = preprocess_constraints_for_meeting_schedule_editor(meeting, sessions)
605605

606+
sessions_for_group = defaultdict(list)
607+
for s in sessions:
608+
sessions_for_group[s.group_id].append(s)
609+
606610
unassigned_sessions = []
607611
for s in sessions:
608612
s.requested_by_person = requested_by_lookup.get(s.requested_by)
@@ -640,6 +644,8 @@ def cubehelix(i, total, hue=1.2, start_angle=0.5):
640644
s.constrained_sessions = list(constrained_sessions_grouped_by_label.items())
641645
s.formatted_constraints = formatted_constraints_for_sessions.get(s.pk, {})
642646

647+
s.other_sessions = [s_other for s_other in sessions_for_group.get(s.group_id) if s != s_other]
648+
643649
assigned = False
644650
for a in assignments_by_session.get(s.pk, []):
645651
timeslot = timeslots_by_pk.get(a.timeslot_id)

ietf/static/ietf/css/ietf.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,14 @@ a.fc-event, .fc-event, .fc-content, .fc-title, .fc-event-container {
11221122
font-weight: bold;
11231123
}
11241124

1125+
.edit-meeting-schedule .session.highlight {
1126+
background-color: #f3f3f3;
1127+
}
1128+
1129+
.edit-meeting-schedule .session.highlight .session-label {
1130+
font-weight: bold;
1131+
}
1132+
11251133
.edit-meeting-schedule .session.dragging {
11261134
opacity: 0.1;
11271135
transition: opacity 0.4s;
@@ -1277,3 +1285,7 @@ a.fc-event, .fc-event, .fc-content, .fc-title, .fc-event-container {
12771285
font-style: italic;
12781286
}
12791287

1288+
.edit-meeting-schedule .scheduling-panel .session-info-container .other-session:hover {
1289+
cursor: default;
1290+
background-color: #eee;
1291+
}

ietf/static/ietf/js/edit-meeting-schedule.js

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,30 @@ jQuery(document).ready(function () {
3636

3737
return res;
3838
}
39-
4039

4140
// selecting
4241
function selectSessionElement(element) {
4342
if (element) {
4443
sessions.not(element).removeClass("selected");
4544
jQuery(element).addClass("selected");
45+
4646
showConstraintHints(element.id.slice("session".length));
47+
4748
let sessionInfoContainer = content.find(".scheduling-panel .session-info-container");
4849
sessionInfoContainer.html(jQuery(element).find(".session-info").html());
49-
sessionInfoContainer.find('[data-original-title]').tooltip();
50-
let time = jQuery(element).closest(".timeslot").find(".time-label").text() || "";
51-
sessionInfoContainer.find('.time').text(time.replace(new RegExp(" ", "g"), ""));
50+
51+
sessionInfoContainer.find("[data-original-title]").tooltip();
52+
53+
sessionInfoContainer.find(".time").text(jQuery(element).closest(".timeslot").data('scheduledatlabel'));
54+
55+
sessionInfoContainer.find(".other-session").each(function () {
56+
let scheduledAt = sessions.filter("#session" + this.dataset.othersessionid).closest(".timeslot").data('scheduledatlabel');
57+
let timeElement = jQuery(this).find(".time");
58+
if (scheduledAt)
59+
timeElement.text(timeElement.data("scheduled").replace("{time}", ));
60+
else
61+
timeElement.text(timeElement.data("notscheduled"));
62+
});
5263
}
5364
else {
5465
sessions.removeClass("selected");
@@ -87,6 +98,8 @@ jQuery(document).ready(function () {
8798
}
8899

89100
content.on("click", function (event) {
101+
if (jQuery(event.target).is(".session-info-container") || jQuery(event.target).closest(".session-info-container").length > 0)
102+
return;
90103
selectSessionElement(null);
91104
});
92105

@@ -315,6 +328,10 @@ jQuery(document).ready(function () {
315328
function sortUnassigned() {
316329
let sortBy = content.find("select[name=sort_unassigned]").val();
317330

331+
function extractId(e) {
332+
return e.id.slice("session".length);
333+
}
334+
318335
function extractName(e) {
319336
return e.querySelector(".session-label").innerHTML;
320337
}
@@ -333,13 +350,13 @@ jQuery(document).ready(function () {
333350

334351
let keyFunctions = [];
335352
if (sortBy == "name")
336-
keyFunctions = [extractName, extractDuration];
353+
keyFunctions = [extractName, extractDuration, extractId];
337354
else if (sortBy == "parent")
338-
keyFunctions = [extractParent, extractName, extractDuration];
355+
keyFunctions = [extractParent, extractName, extractDuration, extractId];
339356
else if (sortBy == "duration")
340-
keyFunctions = [extractDuration, extractParent, extractName];
357+
keyFunctions = [extractDuration, extractParent, extractName, extractId];
341358
else if (sortBy == "comments")
342-
keyFunctions = [extractComments, extractParent, extractName, extractDuration];
359+
keyFunctions = [extractComments, extractParent, extractName, extractDuration, extractId];
343360

344361
let unassignedSessionsContainer = content.find(".unassigned-sessions .drop-target");
345362

@@ -388,5 +405,12 @@ jQuery(document).ready(function () {
388405

389406
timeslotGroupInputs.on("click change", updateTimeslotGroupToggling);
390407
updateTimeslotGroupToggling();
408+
409+
// session info
410+
content.find(".session-info-container").on("mouseover", ".other-session", function (event) {
411+
sessions.filter("#session" + this.dataset.othersessionid).addClass("highlight");
412+
}).on("mouseleave", ".other-session", function (event) {
413+
sessions.filter("#session" + this.dataset.othersessionid).removeClass("highlight");
414+
});
391415
});
392416

ietf/templates/meeting/edit_meeting_schedule.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
<div class="timeslots" data-roomcapacity="{{ room.capacity }}">
8383

8484
{% for t in timeslots %}
85-
<div id="timeslot{{ t.pk }}" class="timeslot {{ t.start_end_group }}" data-start="{{ t.time.isoformat }}" data-end="{{ t.end_time.isoformat }}" data-duration="{{ t.duration.total_seconds }}" style="width: {{ t.layout_width }}rem;">
85+
<div id="timeslot{{ t.pk }}" class="timeslot {{ t.start_end_group }}" data-start="{{ t.time.isoformat }}" data-end="{{ t.end_time.isoformat }}" data-duration="{{ t.duration.total_seconds }}" data-scheduledatlabel="{{ t.time|date:"l G:i" }}-{{ t.end_time|date:"G:i" }}" style="width: {{ t.layout_width }}rem;">
8686
<div class="time-label">
8787
{{ t.time|date:"G:i" }} - {{ t.end_time|date:"G:i" }}
8888
</div>

ietf/templates/meeting/edit_meeting_schedule_session.html

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,12 @@
3030
<span class="time pull-right"></span>
3131
{{ session.scheduling_label }}
3232
&middot; {{ session.requested_duration_in_hours }}h
33-
{% if session.group %}&middot; {% if session.group.is_bof %}BoF{% else %}{{ session.group.type.name }}{% endif %}{% endif %}
34-
{% if session.attendees != None %}&middot; {{ session.attendees }} <i class="fa fa-user-o"></i>{% endif %}
33+
{% if session.group %}
34+
&middot; {% if session.group.is_bof %}BoF{% else %}{{ session.group.type.name }}{% endif %}
35+
{% endif %}
36+
{% if session.attendees != None %}
37+
&middot; {{ session.attendees }} <i class="fa fa-user-o"></i>
38+
{% endif %}
3539
</strong>
3640
</div>
3741

@@ -75,5 +79,9 @@
7579
{% endfor %}
7680
</div>
7781
{% endif %}
82+
83+
{% for s in session.other_sessions %}
84+
<div class="other-session" data-othersessionid="{{ s.pk }}"><i class="fa fa-calendar"></i> Other session <span class="time" data-scheduled="scheduled: {time}" data-notscheduled="not yet scheduled"></span></div>
85+
{% endfor %}
7886
</div>
7987
</div>

0 commit comments

Comments
 (0)