Update migrations and fix a few failing tests. Branch ready for merge.
- Legacy-Id: 19571
This commit is contained in:
parent
bcd37edfcd
commit
0706f8519f
|
@ -694,21 +694,21 @@ def is_special_agenda_item(assignment):
|
||||||
def should_show_agenda_session_buttons(assignment):
|
def should_show_agenda_session_buttons(assignment):
|
||||||
"""Should this agenda item show the session buttons (jabber link, etc)?
|
"""Should this agenda item show the session buttons (jabber link, etc)?
|
||||||
|
|
||||||
In IETF-111 and earlier, office hours sessions were designated by a name ending
|
In IETF-112 and earlier, office hours sessions were designated by a name ending
|
||||||
with ' office hours' and belonged to the IESG or some other group. This led to
|
with ' office hours' and belonged to the IESG or some other group. This led to
|
||||||
incorrect session buttons being displayed. Suppress session buttons for
|
incorrect session buttons being displayed. Suppress session buttons for
|
||||||
when name ends with 'office hours' in the pre-111 meetings.
|
when name ends with 'office hours' in the pre-112 meetings.
|
||||||
>>> from collections import namedtuple # use to build mock objects
|
>>> from collections import namedtuple # use to build mock objects
|
||||||
>>> mock_meeting = namedtuple('t3', ['number'])
|
>>> mock_meeting = namedtuple('t3', ['number'])
|
||||||
>>> mock_session = namedtuple('t2', ['name'])
|
>>> mock_session = namedtuple('t2', ['name'])
|
||||||
>>> mock_assignment = namedtuple('t1', ['meeting', 'session']) # meeting must be a callable
|
>>> mock_assignment = namedtuple('t1', ['meeting', 'session']) # meeting must be a callable
|
||||||
>>> factory = lambda num, name: mock_assignment(session=mock_session(name), meeting=lambda: mock_meeting(num))
|
>>> factory = lambda num, name: mock_assignment(session=mock_session(name), meeting=lambda: mock_meeting(num))
|
||||||
>>> test_cases = [('105', 'acme office hours'), ('111', 'acme office hours')]
|
>>> test_cases = [('105', 'acme office hours'), ('112', 'acme office hours')]
|
||||||
>>> any(should_show_agenda_session_buttons(factory(*tc)) for tc in test_cases)
|
>>> any(should_show_agenda_session_buttons(factory(*tc)) for tc in test_cases)
|
||||||
False
|
False
|
||||||
>>> test_cases = [('interim-2020-acme-112', 'acme'), ('112', 'acme'), ('150', 'acme'), ('105', 'acme'),]
|
>>> test_cases = [('interim-2020-acme-113', 'acme'), ('113', 'acme'), ('150', 'acme'), ('105', 'acme'),]
|
||||||
>>> test_cases.extend([('111', 'acme'), ('interim-2020-acme-112', 'acme office hours')])
|
>>> test_cases.extend([('112', 'acme'), ('interim-2020-acme-113', 'acme office hours')])
|
||||||
>>> test_cases.extend([('112', 'acme office hours'), ('150', 'acme office hours')])
|
>>> test_cases.extend([('113', 'acme office hours'), ('150', 'acme office hours')])
|
||||||
>>> all(should_show_agenda_session_buttons(factory(*tc)) for tc in test_cases)
|
>>> all(should_show_agenda_session_buttons(factory(*tc)) for tc in test_cases)
|
||||||
True
|
True
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Copyright The IETF Trust 2021 All Rights Reserved
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('name', '0033_populate_agendafiltertypename'),
|
||||||
|
('group', '0049_auto_20211019_1136'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='groupfeatures',
|
||||||
|
name='agenda_filter_type',
|
||||||
|
field=models.ForeignKey(default='none', on_delete=django.db.models.deletion.PROTECT, to='name.AgendaFilterTypeName'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Copyright The IETF Trust 2021 All Rights Reserved
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def forward(apps, schema_editor):
|
||||||
|
GroupFeatures = apps.get_model('group', 'GroupFeatures')
|
||||||
|
|
||||||
|
# map AgendaFilterTypeName slug to group types - unlisted get 'none'
|
||||||
|
filter_types = dict(
|
||||||
|
# list previously hard coded in agenda view, plus 'review'
|
||||||
|
normal={'wg', 'ag', 'rg', 'rag', 'iab', 'program', 'review'},
|
||||||
|
heading={'area', 'ietf', 'irtf'},
|
||||||
|
special={'team', 'adhoc'},
|
||||||
|
)
|
||||||
|
|
||||||
|
for ft, group_types in filter_types.items():
|
||||||
|
for gf in GroupFeatures.objects.filter(type__slug__in=group_types):
|
||||||
|
gf.agenda_filter_type_id = ft
|
||||||
|
gf.save()
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor):
|
||||||
|
pass # nothing to do, model will be deleted anyway
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('group', '0050_groupfeatures_agenda_filter_type'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(forward, reverse),
|
||||||
|
]
|
24
ietf/group/migrations/0052_groupfeatures_session_purposes.py
Normal file
24
ietf/group/migrations/0052_groupfeatures_session_purposes.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Copyright The IETF Trust 2021 All Rights Reserved
|
||||||
|
|
||||||
|
# Generated by Django 2.2.24 on 2021-09-26 11:29
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
import ietf.group.models
|
||||||
|
import ietf.name.models
|
||||||
|
import jsonfield.fields
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('group', '0051_populate_groupfeatures_agenda_filter_type'),
|
||||||
|
('name', '0034_sessionpurposename'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='groupfeatures',
|
||||||
|
name='session_purposes',
|
||||||
|
field=jsonfield.fields.JSONField(default=[], help_text='Allowed session purposes for this group type', max_length=256, validators=[ietf.group.models.JSONForeignKeyListValidator(ietf.name.models.SessionPurposeName)]),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,64 @@
|
||||||
|
# Copyright The IETF Trust 2021 All Rights Reserved
|
||||||
|
|
||||||
|
# Generated by Django 2.2.24 on 2021-09-26 11:29
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
default_purposes = dict(
|
||||||
|
adhoc=['presentation'],
|
||||||
|
adm=['closed_meeting', 'officehours'],
|
||||||
|
ag=['regular'],
|
||||||
|
area=['regular'],
|
||||||
|
dir=['open_meeting', 'presentation', 'regular', 'social', 'tutorial'],
|
||||||
|
iab=['closed_meeting', 'regular'],
|
||||||
|
iabasg=['closed_meeting', 'officehours', 'open_meeting'],
|
||||||
|
iana=['officehours'],
|
||||||
|
iesg=['closed_meeting', 'open_meeting'],
|
||||||
|
ietf=['admin', 'plenary', 'presentation', 'social'],
|
||||||
|
irtf=[],
|
||||||
|
ise=['officehours'],
|
||||||
|
isoc=['officehours', 'open_meeting', 'presentation'],
|
||||||
|
nomcom=['closed_meeting', 'officehours'],
|
||||||
|
program=['regular', 'tutorial'],
|
||||||
|
rag=['regular'],
|
||||||
|
review=['open_meeting', 'social'],
|
||||||
|
rfcedtyp=['officehours'],
|
||||||
|
rg=['regular'],
|
||||||
|
team=['coding', 'presentation', 'social', 'tutorial'],
|
||||||
|
wg=['regular'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def forward(apps, schema_editor):
|
||||||
|
GroupFeatures = apps.get_model('group', 'GroupFeatures')
|
||||||
|
SessionPurposeName = apps.get_model('name', 'SessionPurposeName')
|
||||||
|
|
||||||
|
# verify that we're not about to use an invalid purpose
|
||||||
|
for purposes in default_purposes.values():
|
||||||
|
for purpose in purposes:
|
||||||
|
SessionPurposeName.objects.get(pk=purpose) # throws an exception unless exists
|
||||||
|
|
||||||
|
for type_, purposes in default_purposes.items():
|
||||||
|
GroupFeatures.objects.filter(
|
||||||
|
type=type_
|
||||||
|
).update(
|
||||||
|
session_purposes=purposes
|
||||||
|
)
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor):
|
||||||
|
GroupFeatures = apps.get_model('group', 'GroupFeatures')
|
||||||
|
GroupFeatures.objects.update(session_purposes=[]) # clear back out to default
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('group', '0052_groupfeatures_session_purposes'),
|
||||||
|
('name', '0035_populate_sessionpurposename'),
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(forward, reverse),
|
||||||
|
]
|
|
@ -17,7 +17,7 @@ from django.dispatch import receiver
|
||||||
import debug # pyflakes:ignore
|
import debug # pyflakes:ignore
|
||||||
|
|
||||||
from ietf.group.colors import fg_group_colors, bg_group_colors
|
from ietf.group.colors import fg_group_colors, bg_group_colors
|
||||||
from ietf.name.models import (GroupStateName, GroupTypeName, DocTagName, GroupMilestoneStateName, RoleName,
|
from ietf.name.models import (GroupStateName, GroupTypeName, DocTagName, GroupMilestoneStateName, RoleName,
|
||||||
AgendaTypeName, AgendaFilterTypeName, ExtResourceName, SessionPurposeName)
|
AgendaTypeName, AgendaFilterTypeName, ExtResourceName, SessionPurposeName)
|
||||||
from ietf.person.models import Email, Person
|
from ietf.person.models import Email, Person
|
||||||
from ietf.utils.db import IETFJSONField
|
from ietf.utils.db import IETFJSONField
|
||||||
|
@ -264,8 +264,8 @@ class GroupFeatures(models.Model):
|
||||||
groupman_authroles = IETFJSONField(max_length=128, accepted_empty_values=[[], {}], blank=False, default=["Secretariat",])
|
groupman_authroles = IETFJSONField(max_length=128, accepted_empty_values=[[], {}], blank=False, default=["Secretariat",])
|
||||||
matman_roles = IETFJSONField(max_length=128, accepted_empty_values=[[], {}], blank=False, default=["ad","chair","delegate","secr"])
|
matman_roles = IETFJSONField(max_length=128, accepted_empty_values=[[], {}], blank=False, default=["ad","chair","delegate","secr"])
|
||||||
role_order = IETFJSONField(max_length=128, accepted_empty_values=[[], {}], blank=False, default=["chair","secr","member"],
|
role_order = IETFJSONField(max_length=128, accepted_empty_values=[[], {}], blank=False, default=["chair","secr","member"],
|
||||||
help_text="The order in which roles are shown, for instance on photo pages. Enter valid JSON.")
|
help_text="The order in which roles are shown, for instance on photo pages. Enter valid JSON.")
|
||||||
session_purposes = jsonfield.JSONField(max_length=256, blank=False, default=[],
|
session_purposes = IETFJSONField(max_length=256, accepted_empty_values=[[], {}], blank=False, default=[],
|
||||||
help_text="Allowed session purposes for this group type",
|
help_text="Allowed session purposes for this group type",
|
||||||
validators=[JSONForeignKeyListValidator(SessionPurposeName)])
|
validators=[JSONForeignKeyListValidator(SessionPurposeName)])
|
||||||
|
|
||||||
|
|
18
ietf/meeting/migrations/0050_session_on_agenda.py
Normal file
18
ietf/meeting/migrations/0050_session_on_agenda.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 2.2.24 on 2021-10-22 06:58
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('meeting', '0049_session_purpose'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='session',
|
||||||
|
name='on_agenda',
|
||||||
|
field=models.BooleanField(default=True, help_text='Is this session visible on the meeting agenda?'),
|
||||||
|
),
|
||||||
|
]
|
39
ietf/meeting/migrations/0051_populate_session_on_agenda.py
Normal file
39
ietf/meeting/migrations/0051_populate_session_on_agenda.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# Generated by Django 2.2.24 on 2021-10-22 06:58
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def forward(apps, schema_editor):
|
||||||
|
Session = apps.get_model('meeting', 'Session')
|
||||||
|
SchedTimeSessAssignment = apps.get_model('meeting', 'SchedTimeSessAssignment')
|
||||||
|
# find official assignments that are to private timeslots and fill in session.on_agenda
|
||||||
|
private_assignments = SchedTimeSessAssignment.objects.filter(
|
||||||
|
models.Q(
|
||||||
|
schedule=models.F('session__meeting__schedule')
|
||||||
|
) | models.Q(
|
||||||
|
schedule=models.F('session__meeting__schedule__base')
|
||||||
|
),
|
||||||
|
timeslot__type__private=True,
|
||||||
|
)
|
||||||
|
for pa in private_assignments:
|
||||||
|
pa.session.on_agenda = False
|
||||||
|
pa.session.save()
|
||||||
|
# Also update any sessions to match their purpose's default setting (this intentionally
|
||||||
|
# overrides the timeslot settings above, but that is unlikely to matter because the
|
||||||
|
# purposes will roll out at the same time as the on_agenda field)
|
||||||
|
Session.objects.filter(purpose__on_agenda=False).update(on_agenda=False)
|
||||||
|
Session.objects.filter(purpose__on_agenda=True).update(on_agenda=True)
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor):
|
||||||
|
Session = apps.get_model('meeting', 'Session')
|
||||||
|
Session.objects.update(on_agenda=True) # restore all to default on_agenda=True state
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('meeting', '0050_session_on_agenda'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(forward, reverse),
|
||||||
|
]
|
|
@ -766,7 +766,7 @@ class EditMeetingScheduleTests(IetfSeleniumTestCase):
|
||||||
all of the events needed by the editor.
|
all of the events needed by the editor.
|
||||||
"""
|
"""
|
||||||
# Set up a meeting and a schedule a plain user can edit
|
# Set up a meeting and a schedule a plain user can edit
|
||||||
schedule = ScheduleFactory(owner__user__username="plain")
|
schedule = ScheduleFactory(meeting__type_id='ietf', owner__user__username="plain")
|
||||||
meeting = schedule.meeting
|
meeting = schedule.meeting
|
||||||
|
|
||||||
# Open the editor
|
# Open the editor
|
||||||
|
|
|
@ -3714,7 +3714,7 @@ class EditTests(TestCase):
|
||||||
self.assertEqual(meeting.schedule_set.count(), orig_schedule_count, 'Schedule should not be created')
|
self.assertEqual(meeting.schedule_set.count(), orig_schedule_count, 'Schedule should not be created')
|
||||||
|
|
||||||
def test_edit_session(self):
|
def test_edit_session(self):
|
||||||
session = SessionFactory(group__type_id='team') # type determines allowed session purposes
|
session = SessionFactory(meeting__type_id='ietf', group__type_id='team') # type determines allowed session purposes
|
||||||
self.client.login(username='secretary', password='secretary+password')
|
self.client.login(username='secretary', password='secretary+password')
|
||||||
url = urlreverse('ietf.meeting.views.edit_session', kwargs={'session_id': session.pk})
|
url = urlreverse('ietf.meeting.views.edit_session', kwargs={'session_id': session.pk})
|
||||||
r = self.client.get(url)
|
r = self.client.get(url)
|
||||||
|
|
|
@ -23,7 +23,7 @@ class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('name', '0035_populate_sessionpurposename'),
|
('name', '0035_populate_sessionpurposename'),
|
||||||
('meeting', '0050_populate_session_on_agenda'),
|
('meeting', '0051_populate_session_on_agenda'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
|
Loading…
Reference in a new issue