fix: Use session name instead of timeslot name on agenda (#5086)

* fix: Use session name instead of timeslot name on agenda

* test: Fix failing playwright test

* test: Test name/slotName values from agenda_extract_schedule()

* chore: Migrate sessions to use timeslot names for IETF meetings
This commit is contained in:
Jennifer Richards 2023-02-07 16:40:23 -04:00 committed by GitHub
parent 9a673a27ac
commit 6cfbab63ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 84 additions and 5 deletions

View file

@ -257,16 +257,17 @@ const meetingEvents = computed(() => {
acc.lastDate = itemDate.toISODate()
// -> Add session header row
if (item.type === 'regular' && acc.lastTypeName !== `${item.type}-${item.name}`) {
const typeName = `${item.type}-${item.slotName}`
if (item.type === 'regular' && acc.lastTypeName !== typeName) {
acc.result.push({
key: `sesshd-${item.id}`,
displayType: 'session-head',
timeslot: itemTimeSlot,
name: `${item.adjustedStart.toFormat('cccc')} ${item.name}`,
name: `${item.adjustedStart.toFormat('cccc')} ${item.slotName}`,
cssClasses: 'agenda-table-display-session-head' + (isLive ? ' agenda-table-live' : '')
})
}
acc.lastTypeName = `${item.type}-${item.name}`
acc.lastTypeName = typeName
// -> Populate event links
const links = []

View file

@ -0,0 +1,41 @@
# Generated by Django 2.2.28 on 2023-02-06 22:20
from django.db import migrations
from django.db.models import ExpressionWrapper, F, IntegerField
def forward(apps, schema_editor):
Meeting = apps.get_model('meeting', 'Meeting')
meetings = Meeting.objects.filter(type='ietf', schedule__isnull=False).annotate(
number_as_int=ExpressionWrapper(F('number'), output_field=IntegerField())
).order_by('date')
# print('session.pk,meeting.number,session.name,timeslot.name')
for m in meetings.filter(number_as_int__lt=91):
# until meeting 91, TimeSlots had the more descriptive names
for assignment in m.schedule.assignments.exclude(session__type='regular').exclude(session__name=F('timeslot__name')):
# print(f'{assignment.session.pk},{m.number},{assignment.session.name},{assignment.timeslot.name}')
assignment.session.name = assignment.timeslot.name
assignment.session.save()
# meetings 91-98 had no differences or were better off with session names as they were
for m in meetings.filter(number_as_int__gte=99):
# for meetings 99+, TimeSlots again had the better names
for assignment in m.schedule.assignments.exclude(session__type='regular').exclude(session__name=F('timeslot__name')):
# print(f'{assignment.session.pk},{m.number},{assignment.session.name},{assignment.timeslot.name}')
assignment.session.name = assignment.timeslot.name
assignment.session.save()
def reverse(apps, schema_editor):
pass # can't undo
class Migration(migrations.Migration):
dependencies = [
('meeting', '0058_meeting_time_zone_not_blank'),
]
operations = [
migrations.RunPython(forward, reverse),
]

View file

@ -172,6 +172,42 @@ class AgendaApiTests(TestCase):
self.assertEqual(shown['room'], room.name)
self.assertEqual(shown['location'], {'name': room.floorplan.name, 'short': room.floorplan.short})
def test_agenda_extract_schedule_names(self):
meeting = MeetingFactory(type_id='ietf')
named_timeslots = TimeSlotFactory.create_batch(2, meeting=meeting, name='Timeslot Name')
unnamed_timeslots = TimeSlotFactory.create_batch(2, meeting=meeting, name='')
named_sessions = SessionFactory.create_batch(2, meeting=meeting, name='Session Name')
unnamed_sessions = SessionFactory.create_batch(2, meeting=meeting, name='')
pk_with = {
'both named': named_sessions[0].timeslotassignments.create(
schedule=meeting.schedule,
timeslot=named_timeslots[0],
).pk,
'session named': named_sessions[1].timeslotassignments.create(
schedule=meeting.schedule,
timeslot=unnamed_timeslots[0],
).pk,
'timeslot named': unnamed_sessions[0].timeslotassignments.create(
schedule=meeting.schedule,
timeslot=named_timeslots[1],
).pk,
'neither named': unnamed_sessions[1].timeslotassignments.create(
schedule=meeting.schedule,
timeslot=unnamed_timeslots[1],
).pk,
}
processed = preprocess_assignments_for_agenda(meeting.schedule.assignments.all(), meeting)
AgendaKeywordTagger(assignments=processed).apply()
extracted = {item.pk: agenda_extract_schedule(item) for item in processed}
self.assertEqual(extracted[pk_with['both named']]['name'], 'Session Name')
self.assertEqual(extracted[pk_with['both named']]['slotName'], 'Timeslot Name')
self.assertEqual(extracted[pk_with['session named']]['name'], 'Session Name')
self.assertEqual(extracted[pk_with['session named']]['slotName'], '')
self.assertEqual(extracted[pk_with['timeslot named']]['name'], '')
self.assertEqual(extracted[pk_with['timeslot named']]['slotName'], 'Timeslot Name')
self.assertEqual(extracted[pk_with['neither named']]['name'], '')
self.assertEqual(extracted[pk_with['neither named']]['slotName'], '')
class MeetingTests(BaseMeetingTestCase):
def test_meeting_agenda(self):

View file

@ -1704,7 +1704,8 @@ def agenda_extract_schedule (item):
} if (item.timeslot.show_location and item.timeslot.location and item.timeslot.location.floorplan) else {},
"acronym": item.acronym,
"duration": item.timeslot.duration.seconds,
"name": item.timeslot.name,
"name": item.session.name,
"slotName": item.timeslot.name,
"startDateTime": item.timeslot.time.isoformat(),
"status": item.session.current_status,
"type": item.session.type.slug,

View file

@ -213,7 +213,7 @@ test.describe('past - desktop', () => {
const headerRow = page.locator(`#agenda-rowid-sesshd-${event.id}`)
await expect(headerRow).toBeVisible()
await expect(headerRow.locator('.agenda-table-cell-ts')).toContainText(eventTimeSlot)
await expect(headerRow.locator('.agenda-table-cell-name')).toContainText(`${DateTime.fromISO(event.startDateTime).toFormat('cccc')} ${event.name}`)
await expect(headerRow.locator('.agenda-table-cell-name')).toContainText(`${DateTime.fromISO(event.startDateTime).toFormat('cccc')} ${event.slotName}`)
}
// Timeslot
await expect(row.locator('.agenda-table-cell-ts')).toContainText('—')