Skip to content

Commit 2e6f26a

Browse files
committed
Moves Important Dates into the datatracker. Fixes ietf-tools#2338. Commit ready for merge.
- Legacy-Id: 13957
1 parent 59886b9 commit 2e6f26a

18 files changed

Lines changed: 10433 additions & 9758 deletions

ietf/meeting/admin.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from ietf.meeting.models import (Meeting, Room, Session, TimeSlot, Constraint, Schedule,
44
SchedTimeSessAssignment, ResourceAssociation, FloorPlan, UrlResource,
5-
SessionPresentation)
5+
SessionPresentation, ImportantDate, )
66

77

88
class UrlResourceAdmin(admin.ModelAdmin):
@@ -125,3 +125,10 @@ class SessionPresentationAdmin(admin.ModelAdmin):
125125
list_filter = ['session__meeting', 'document__group__acronym', ]
126126
raw_id_fields = ['document', 'session', ]
127127
admin.site.register(SessionPresentation, SessionPresentationAdmin)
128+
129+
class ImportantDateAdmin(admin.ModelAdmin):
130+
model = ImportantDate
131+
list_display = ['meeting', 'name', 'date']
132+
ordering = ['-meeting__number','date',]
133+
134+
admin.site.register(ImportantDate,ImportantDateAdmin)

ietf/meeting/helpers.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
from ietf.liaisons.utils import get_person_for_user
2323
from ietf.mailtrigger.utils import gather_address_lists
2424
from ietf.person.models import Person
25-
from ietf.meeting.models import Meeting, Schedule, TimeSlot, SchedTimeSessAssignment
25+
from ietf.meeting.models import Meeting, Schedule, TimeSlot, SchedTimeSessAssignment, ImportantDate
26+
from ietf.name.models import ImportantDateName
2627
from ietf.utils.history import find_history_active_at, find_history_replacements_active_at
2728
from ietf.utils.mail import send_mail
2829
from ietf.utils.pipe import pipe
@@ -128,6 +129,13 @@ def get_meeting(num=None,type_in=['ietf',]):
128129
else:
129130
raise Http404("No such meeting found: %s" % num)
130131

132+
def get_ietf_meeting(num=None):
133+
if num:
134+
meetings = Meeting.objects.filter(number=num)
135+
else:
136+
meetings = Meeting.objects.filter(type='ietf',date__gte=datetime.datetime.today()-datetime.timedelta(days=31)).order_by('date')
137+
return meetings.first()
138+
131139
def get_schedule(meeting, name=None):
132140
if name is None:
133141
schedule = meeting.agenda
@@ -608,3 +616,9 @@ def update_interim_session_assignment(form):
608616
timeslot=slot,
609617
session=session,
610618
schedule=session.meeting.agenda)
619+
620+
def populate_important_dates(meeting):
621+
assert ImportantDate.objects.filter(meeting=meeting).exists() is False
622+
assert meeting.type_id=='ietf'
623+
for datename in ImportantDateName.objects.filter(used=True):
624+
ImportantDate.objects.create(meeting=meeting,name=datename,date=meeting.date+datetime.timedelta(days=datename.default_offset_days))
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.10.7 on 2017-07-20 06:10
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
import django.db.models.deletion
7+
8+
9+
class Migration(migrations.Migration):
10+
11+
dependencies = [
12+
('name', '0025_add-important-dates'),
13+
('meeting', '0052_floorplan_short'),
14+
]
15+
16+
operations = [
17+
migrations.CreateModel(
18+
name='ImportantDate',
19+
fields=[
20+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21+
('date', models.DateField()),
22+
('meeting', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='meeting.Meeting')),
23+
('name', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='name.ImportantDateName')),
24+
],
25+
options={'ordering': ['-meeting','date']},
26+
),
27+
]
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.10.7 on 2017-07-20 06:14
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations
6+
7+
import datetime
8+
9+
def forward(apps,schema_editor):
10+
Meeting = apps.get_model('meeting','Meeting')
11+
ImportantDate = apps.get_model('meeting', 'ImportantDate')
12+
ImportantDateName = apps.get_model('name', 'ImportantDateName')
13+
14+
for num in [98,99]:
15+
meeting = Meeting.objects.get(number=num)
16+
for datename in ImportantDateName.objects.filter(used=True):
17+
ImportantDate.objects.create(meeting=meeting,name=datename,date=meeting.date+datetime.timedelta(days=datename.default_offset_days-1))
18+
19+
ImportantDate.objects.filter(meeting__number=99,name__slug='openreg').update(date='2017-03-27')
20+
21+
ImportantDate.objects.filter(meeting__number=98,name__slug='openreg').update(date='2016-11-28')
22+
ImportantDate.objects.filter(meeting__number=98,name__slug='opensched').update(date='2016-12-19')
23+
24+
def reverse(apps,schema_editor):
25+
ImportantDate = apps.get_model('meeting', 'ImportantDate')
26+
ImportantDate.objects.filter(meeting__number__in=[99,98]).delete()
27+
28+
class Migration(migrations.Migration):
29+
30+
dependencies = [
31+
('meeting', '0053_important_date'),
32+
('name', '0026_popuulate-important-date-names'),
33+
]
34+
35+
operations = [
36+
migrations.RunPython(forward,reverse),
37+
]
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.10.7 on 2017-07-21 01:35
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations
6+
import datetime
7+
8+
def forward(apps, schema_editor):
9+
ImportantDate = apps.get_model('meeting','ImportantDate')
10+
Meeting = apps.get_model('meeting','Meeting')
11+
for m in Meeting.objects.filter(type='ietf').exclude(importantdate__isnull=False):
12+
if m.idsubmit_cutoff_day_offset_00 == m.idsubmit_cutoff_day_offset_01 :
13+
ImportantDate.objects.create(
14+
name_id='idcutoff',
15+
meeting=m,
16+
date=m.date-datetime.timedelta(days=m.idsubmit_cutoff_day_offset_00)
17+
)
18+
else:
19+
ImportantDate.objects.create(
20+
name_id='00cutoff',
21+
meeting=m,
22+
date=m.date-datetime.timedelta(days=m.idsubmit_cutoff_day_offset_00)
23+
)
24+
ImportantDate.objects.create(
25+
name_id='01cutoff',
26+
meeting=m,
27+
date=m.date-datetime.timedelta(days=m.idsubmit_cutoff_day_offset_01)
28+
)
29+
30+
31+
def reverse(apps, schema_editor):
32+
Meeting = apps.get_model('meeting','Meeting')
33+
# This is a simple reverse implementation. If a reverse is needed a significant
34+
# time after the forward is run (as in multiple meeting cycles), a more considered
35+
# implemenation should be created reflecting any assumptions that have changed in
36+
# that time.
37+
for m in Meeting.objects.filter(type='ietf'):
38+
if m.importantdate_set.count()==2:
39+
m.importantdate_set.all().delete()
40+
41+
class Migration(migrations.Migration):
42+
43+
dependencies = [
44+
('meeting', '0054_earlier_important_dates'),
45+
]
46+
47+
operations = [
48+
migrations.RunPython(forward,reverse)
49+
]

ietf/meeting/models.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from ietf.doc.models import Document
2222
from ietf.group.models import Group
2323
from ietf.group.utils import can_manage_materials
24-
from ietf.name.models import MeetingTypeName, TimeSlotTypeName, SessionStatusName, ConstraintName, RoomResourceName
24+
from ietf.name.models import MeetingTypeName, TimeSlotTypeName, SessionStatusName, ConstraintName, RoomResourceName, ImportantDateName
2525
from ietf.person.models import Person
2626
from ietf.utils.storage import NoLocationMigrationFileSystemStorage
2727
from ietf.utils.text import xslugify
@@ -109,13 +109,25 @@ def end_date(self):
109109

110110
def get_00_cutoff(self):
111111
start_date = datetime.datetime(year=self.date.year, month=self.date.month, day=self.date.day, tzinfo=pytz.utc)
112-
cutoff_date = start_date - datetime.timedelta(days=self.idsubmit_cutoff_day_offset_00)
112+
importantdate = self.importantdate_set.filter(name_id='idcutoff').first()
113+
if not importantdate:
114+
importantdate = self.importantdate_set.filter(name_id='00cutoff').first()
115+
if importantdate:
116+
cutoff_date = importantdate.date
117+
else:
118+
cutoff_date = start_date + datetime.timedelta(days=ImportantDateName.objects.get(slug='idcutoff').default_offset_days)
113119
cutoff_time = cutoff_date + self.idsubmit_cutoff_time_utc
114120
return cutoff_time
115121

116122
def get_01_cutoff(self):
117123
start_date = datetime.datetime(year=self.date.year, month=self.date.month, day=self.date.day, tzinfo=pytz.utc)
118-
cutoff_date = start_date - datetime.timedelta(days=self.idsubmit_cutoff_day_offset_01)
124+
importantdate = self.importantdate_set.filter(name_id='idcutoff').first()
125+
if not importantdate:
126+
importantdate = self.importantdate_set.filter(name_id='01cutoff').first()
127+
if importantdate:
128+
cutoff_date = importantdate.date
129+
else:
130+
cutoff_date = start_date + datetime.timedelta(days=ImportantDateName.objects.get(slug='idcutoff').default_offset_days)
119131
cutoff_time = cutoff_date + self.idsubmit_cutoff_time_utc
120132
return cutoff_time
121133

@@ -1100,3 +1112,10 @@ def agenda_file(self):
11001112
self._agenda_file = "%s/agenda/%s" % (self.meeting.number, filename)
11011113

11021114
return self._agenda_file
1115+
1116+
class ImportantDate(models.Model):
1117+
meeting = models.ForeignKey(Meeting)
1118+
date = models.DateField()
1119+
name = models.ForeignKey(ImportantDateName)
1120+
class Meta:
1121+
ordering = ["-meeting","date", ]

ietf/meeting/resources.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from ietf.meeting.models import ( Meeting, ResourceAssociation, Constraint, Room, Schedule, Session,
1111
TimeSlot, SchedTimeSessAssignment, SessionPresentation, FloorPlan,
12-
UrlResource)
12+
UrlResource, ImportantDate )
1313

1414
from ietf.name.resources import MeetingTypeNameResource
1515
class MeetingResource(ModelResource):
@@ -279,3 +279,21 @@ class Meta:
279279
}
280280
api.meeting.register(UrlResourceResource())
281281

282+
283+
284+
from ietf.name.resources import ImportantDateNameResource
285+
class ImportantDateResource(ModelResource):
286+
meeting = ToOneField(MeetingResource, 'meeting')
287+
name = ToOneField(ImportantDateNameResource, 'name')
288+
class Meta:
289+
queryset = ImportantDate.objects.all()
290+
serializer = api.Serializer()
291+
cache = SimpleCache()
292+
#resource_name = 'importantdate'
293+
filtering = {
294+
"id": ALL,
295+
"date": ALL,
296+
"meeting": ALL_WITH_RELATIONS,
297+
"name": ALL_WITH_RELATIONS,
298+
}
299+
api.meeting.register(ImportantDateResource())

ietf/meeting/tests_views.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from ietf.meeting.helpers import can_approve_interim_request, can_view_interim_request
2323
from ietf.meeting.helpers import send_interim_approval_request
2424
from ietf.meeting.helpers import send_interim_cancellation_notice
25-
from ietf.meeting.helpers import send_interim_minutes_reminder
25+
from ietf.meeting.helpers import send_interim_minutes_reminder, populate_important_dates
2626
from ietf.meeting.models import Session, TimeSlot, Meeting
2727
from ietf.meeting.test_data import make_meeting_test_data, make_interim_meeting
2828
from ietf.meeting.utils import finalize
@@ -408,6 +408,14 @@ def test_feed(self):
408408
self.assertTrue("agenda" in unicontent(r))
409409
self.assertTrue(session.group.acronym in unicontent(r))
410410

411+
def test_important_dates(self):
412+
meeting=MeetingFactory(type_id='ietf')
413+
populate_important_dates(meeting)
414+
url = urlreverse('ietf.meeting.views.important_dates',kwargs={'num':meeting.number})
415+
r = self.client.get(url)
416+
self.assertEqual(r.status_code, 200)
417+
self.assertTrue(str(meeting.importantdate_set.first().date) in unicontent(r))
418+
411419
class EditTests(TestCase):
412420
def setUp(self):
413421
# make sure we have the colors of the area

ietf/meeting/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@
9090
url(r'^proceedings/attendees/$', views.proceedings_attendees),
9191
url(r'^proceedings/overview/$', views.proceedings_overview),
9292
url(r'^proceedings/progress-report/$', views.proceedings_progress_report),
93+
url(r'^important-dates/$', views.important_dates),
94+
9395
]
9496

9597
urlpatterns = [

ietf/meeting/views.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
from ietf.meeting.helpers import get_all_assignments_from_schedule
4747
from ietf.meeting.helpers import get_modified_from_assignments
4848
from ietf.meeting.helpers import get_wg_list, find_ads_for_meeting
49-
from ietf.meeting.helpers import get_meeting, get_schedule, agenda_permissions, get_meetings
49+
from ietf.meeting.helpers import get_meeting, get_schedule, agenda_permissions, get_meetings, get_ietf_meeting
5050
from ietf.meeting.helpers import preprocess_assignments_for_agenda, read_agenda_file, read_session_file
5151
from ietf.meeting.helpers import convert_draft_to_pdf, get_earliest_session_date
5252
from ietf.meeting.helpers import can_view_interim_request, can_approve_interim_request
@@ -409,13 +409,13 @@ def agenda(request, num=None, name=None, base=None, ext=None, owner=None, utc=""
409409
".csv": "text/csv; charset=%s"%settings.DEFAULT_CHARSET,
410410
}
411411

412-
meetings = get_meetings(num)
413-
414412
# We do not have the appropriate data in the datatracker for IETF 64 and earlier.
415413
# So that we're not producing misleading pages...
416414

417-
meeting = meetings.first()
418-
if not meetings.exists() or (meeting.number.isdigit() and meeting.number <= 64 and not meeting.agenda.assignments.exists()):
415+
assert num is None or num.isdigit()
416+
417+
meeting = get_ietf_meeting(num)
418+
if not meeting or (meeting.number.isdigit() and int(meeting.number) <= 64 and not meeting.agenda.assignments.exists()):
419419
if ext == '.html':
420420
return HttpResponseRedirect( 'https://www.ietf.org/proceedings/%s' % num )
421421
else:
@@ -2194,4 +2194,19 @@ def api_import_recordings(request, number):
21942194
else:
21952195
return HttpResponse(status=405)
21962196

2197+
def important_dates(request, num=None):
2198+
assert num is None or num.isdigit()
2199+
2200+
meeting = get_ietf_meeting(num)
2201+
if not meeting:
2202+
raise Http404
2203+
base_num = int(meeting.number)
2204+
2205+
meetings=[meeting]
2206+
for i in range(1,3):
2207+
future_meeting = get_ietf_meeting(base_num+i)
2208+
if future_meeting:
2209+
meetings.append(future_meeting)
21972210

2211+
context={'meetings':meetings}
2212+
return render(request, 'meeting/important-dates.html', context)

0 commit comments

Comments
 (0)