Merged in ^/branch/proceedings/6.33.1.dev0@12141 from rcross@amsl.com:
Added meeting proceedings introduction pages: Progress Report and Attendees. Added a data migration to provide proceedings introduction information for IETF 95 and 96. - Legacy-Id: 12150
This commit is contained in:
commit
1a92efb77e
|
@ -1,6 +1,6 @@
|
|||
# -*- conf-mode -*-
|
||||
|
||||
/branch/proceedings/6.33.1.dev0@12111 # Missing data migration to add dbtemplates ?
|
||||
|
||||
/branch/proceedings/6.29.1.dev0@11850 # Merged into /branch/proceedings/6.30.1.dev0, will be merged from there
|
||||
/branch/proceedings/6.29.1.dev0@11856 # Merged into /branch/proceedings/6.30.1.dev0, will be merged from there
|
||||
/personal/rcross/6.29.1.dev0@11765 # Merged into ^/personal/rjs/6.29.1.dev0@11770, will be merged from there
|
||||
|
|
22
ietf/meeting/migrations/0038_auto_20161013_1459.py
Normal file
22
ietf/meeting/migrations/0038_auto_20161013_1459.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
from ietf.meeting.utils import create_proceedings_templates
|
||||
|
||||
def create_attendee_templates(apps, schema_editor):
|
||||
"""Create attendee templates for supported meetings"""
|
||||
Meeting = apps.get_model("meeting", "Meeting")
|
||||
create_proceedings_templates(Meeting.objects.get(number=95))
|
||||
create_proceedings_templates(Meeting.objects.get(number=96))
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('meeting', '0037_change_meta_options_on_sessionpresentation'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(create_attendee_templates),
|
||||
]
|
|
@ -11,6 +11,7 @@ from django.core.urlresolvers import reverse as urlreverse
|
|||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from mock import patch
|
||||
from pyquery import PyQuery
|
||||
from StringIO import StringIO
|
||||
|
||||
|
@ -22,6 +23,7 @@ from ietf.meeting.helpers import send_interim_cancellation_notice
|
|||
from ietf.meeting.helpers import send_interim_minutes_reminder
|
||||
from ietf.meeting.models import Session, TimeSlot, Meeting
|
||||
from ietf.meeting.test_data import make_meeting_test_data, make_interim_meeting
|
||||
from ietf.meeting.utils import finalize
|
||||
from ietf.name.models import SessionStatusName
|
||||
from ietf.utils.test_utils import TestCase, login_testing_unauthorized, unicontent
|
||||
from ietf.utils.mail import outbox
|
||||
|
@ -33,6 +35,7 @@ from ietf.meeting.factories import ( SessionFactory, SessionPresentationFactory,
|
|||
MeetingFactory, FloorPlanFactory )
|
||||
from ietf.doc.factories import DocumentFactory
|
||||
|
||||
|
||||
class MeetingTests(TestCase):
|
||||
def setUp(self):
|
||||
self.materials_dir = os.path.abspath(settings.TEST_MATERIALS_DIR)
|
||||
|
@ -272,41 +275,50 @@ class MeetingTests(TestCase):
|
|||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
def test_proceedings_acknowledgements(self):
|
||||
meeting = make_meeting_test_data()
|
||||
make_meeting_test_data()
|
||||
meeting = MeetingFactory(type_id='ietf', date=datetime.date(2016,7,14), number="96")
|
||||
meeting.acknowledgements = 'test acknowledgements'
|
||||
meeting.save()
|
||||
url = urlreverse('ietf.meeting.views.proceedings_acknowledgements',kwargs={'num':meeting.number})
|
||||
login_testing_unauthorized(self,"secretary",url)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTrue('test acknowledgements' in response.content)
|
||||
|
||||
@patch('urllib2.urlopen')
|
||||
def test_proceedings_attendees(self, mock_urlopen):
|
||||
mock_urlopen.return_value = StringIO('[{"LastName":"Smith","FirstName":"John","Company":"ABC","Country":"US"}]')
|
||||
make_meeting_test_data()
|
||||
meeting = MeetingFactory(type_id='ietf', date=datetime.date(2016,7,14), number="96")
|
||||
finalize(meeting)
|
||||
url = urlreverse('ietf.meeting.views.proceedings_attendees',kwargs={'num':96})
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTrue('Attendee List' in response.content)
|
||||
q = PyQuery(response.content)
|
||||
self.assertEqual(1,len(q("#id_attendees tbody tr")))
|
||||
|
||||
def test_proceedings_overview(self):
|
||||
'''Test proceedings IETF Overview page.
|
||||
Note: old meetings aren't supported so need to add a new meeting then test.
|
||||
'''
|
||||
make_meeting_test_data()
|
||||
# add meeting requires a previous meeting to work
|
||||
date = datetime.date(2016,7,14)
|
||||
Meeting.objects.create(type_id='ietf',date=date,number=96)
|
||||
url = urlreverse('ietf.secr.meetings.views.add')
|
||||
post_data = dict(number='97',city='Seoul',date='2016-11-13',country='KR',
|
||||
time_zone='Asia/Seoul',venue_name='Conrad Seoul',
|
||||
venue_addr='10 Gukjegeumyung-ro',
|
||||
idsubmit_cutoff_day_offset_00=13,
|
||||
idsubmit_cutoff_day_offset_01=20,
|
||||
idsubmit_cutoff_time_utc =datetime.timedelta(hours=23, minutes=59, seconds=59),
|
||||
idsubmit_cutoff_warning_days =datetime.timedelta(days=21),
|
||||
submission_start_day_offset=90,
|
||||
submission_cutoff_day_offset=26,
|
||||
submission_correction_day_offset=50,
|
||||
)
|
||||
self.client.login(username='secretary', password='secretary+password')
|
||||
|
||||
response = self.client.post(url, post_data)
|
||||
self.assertRedirects(response,urlreverse('ietf.secr.meetings.views.main'))
|
||||
url = urlreverse('ietf.meeting.views.proceedings_overview',kwargs={'num':97})
|
||||
meeting = MeetingFactory(type_id='ietf', date=datetime.date(2016,7,14), number="96")
|
||||
finalize(meeting)
|
||||
url = urlreverse('ietf.meeting.views.proceedings_overview',kwargs={'num':96})
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTrue('The Internet Engineering Task Force' in response.content)
|
||||
|
||||
def test_proceedings_progress_report(self):
|
||||
make_meeting_test_data()
|
||||
MeetingFactory(type_id='ietf', date=datetime.date(2016,4,3), number="95")
|
||||
MeetingFactory(type_id='ietf', date=datetime.date(2016,7,14), number="96")
|
||||
|
||||
url = urlreverse('ietf.meeting.views.proceedings_progress_report',kwargs={'num':96})
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTrue('Progress Report' in response.content)
|
||||
|
||||
def test_feed(self):
|
||||
meeting = make_meeting_test_data()
|
||||
session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
|
||||
|
@ -1279,7 +1291,9 @@ class IphoneAppJsonTests(TestCase):
|
|||
self.assertEqual(r.status_code,200)
|
||||
|
||||
class FinalizeProceedingsTests(TestCase):
|
||||
def test_finalize_proceedings(self):
|
||||
@patch('urllib2.urlopen')
|
||||
def test_finalize_proceedings(self, mock_urlopen):
|
||||
mock_urlopen.return_value = StringIO('[{"LastName":"Smith","FirstName":"John","Company":"ABC","Country":"US"}]')
|
||||
make_meeting_test_data()
|
||||
meeting = Meeting.objects.filter(type_id='ietf').order_by('id').last()
|
||||
meeting.session_set.filter(group__acronym='mars').first().sessionpresentation_set.create(document=Document.objects.filter(type='draft').first(),rev=None)
|
||||
|
|
|
@ -78,7 +78,9 @@ type_ietf_only_patterns_id_optional = [
|
|||
url(r'^proceedings(?:.html)?/?$', views.proceedings),
|
||||
url(r'^proceedings(?:.html)?/finalize/?$', views.finalize_proceedings),
|
||||
url(r'^proceedings/acknowledgements/$', views.proceedings_acknowledgements),
|
||||
url(r'^proceedings/attendees/$', views.proceedings_attendees),
|
||||
url(r'^proceedings/overview/$', views.proceedings_overview),
|
||||
url(r'^proceedings/progress-report/$', views.proceedings_progress_report),
|
||||
]
|
||||
|
||||
urlpatterns = [
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
import datetime
|
||||
import json
|
||||
import urllib2
|
||||
import urlparse
|
||||
|
||||
from django.conf import settings
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from ietf.dbtemplate.models import DBTemplate
|
||||
from ietf.meeting.models import Session
|
||||
from ietf.group.utils import can_manage_materials
|
||||
|
||||
|
@ -72,6 +79,35 @@ def sort_sessions(sessions):
|
|||
|
||||
return meeting_sorted
|
||||
|
||||
def create_proceedings_templates(meeting):
|
||||
'''Create DBTemplates for meeting proceedings'''
|
||||
# Get meeting attendees from registration system
|
||||
url = urlparse.urljoin(settings.REGISTRATION_ATTENDEES_BASE_URL,meeting.number)
|
||||
try:
|
||||
attendees = json.load(urllib2.urlopen(url))
|
||||
except (ValueError, urllib2.HTTPError):
|
||||
attendees = []
|
||||
|
||||
if attendees:
|
||||
attendees = sorted(attendees, key = lambda a: a['LastName'])
|
||||
content = render_to_string('meeting/proceedings_attendees_table.html', {
|
||||
'attendees':attendees})
|
||||
DBTemplate.objects.create(
|
||||
path='/meeting/proceedings/%s/attendees.html' % meeting.number,
|
||||
title='IETF %s Attendee List' % meeting.number,
|
||||
type_id='django',
|
||||
content=content)
|
||||
|
||||
# Make copy of default IETF Overview template
|
||||
if not meeting.overview:
|
||||
template = DBTemplate.objects.get(path='/meeting/proceedings/defaults/overview.rst')
|
||||
template.id = None
|
||||
template.path = '/meeting/proceedings/%s/overview.rst' % (meeting.number)
|
||||
template.title = 'IETF %s Proceedings Overview' % (meeting.number)
|
||||
template.save()
|
||||
meeting.overview = template
|
||||
meeting.save()
|
||||
|
||||
def finalize(meeting):
|
||||
end_date = meeting.end_date()
|
||||
end_time = datetime.datetime.combine(end_date, datetime.datetime.min.time())+datetime.timedelta(days=1)
|
||||
|
@ -83,6 +119,8 @@ def finalize(meeting):
|
|||
else:
|
||||
sp.rev = '00'
|
||||
sp.save()
|
||||
|
||||
create_proceedings_templates(meeting)
|
||||
meeting.proceedings_final = True
|
||||
meeting.save()
|
||||
return
|
||||
|
|
|
@ -25,6 +25,7 @@ from django.db.models import Min, Max
|
|||
from django.conf import settings
|
||||
from django.forms.models import modelform_factory, inlineformset_factory
|
||||
from django.forms import ModelForm
|
||||
from django.template import TemplateDoesNotExist
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.functional import curry
|
||||
from django.views.decorators.cache import cache_page
|
||||
|
@ -56,6 +57,7 @@ from ietf.meeting.helpers import send_interim_approval_request
|
|||
from ietf.meeting.helpers import send_interim_announcement_request
|
||||
from ietf.meeting.utils import finalize
|
||||
from ietf.secr.proceedings.utils import handle_upload_file
|
||||
from ietf.secr.proceedings.proc_utils import get_progress_stats
|
||||
from ietf.utils.mail import send_mail_message
|
||||
from ietf.utils.pipe import pipe
|
||||
from ietf.utils.pdf import pdf_pages
|
||||
|
@ -2009,30 +2011,65 @@ def finalize_proceedings(request, num=None):
|
|||
|
||||
return render(request, "meeting/finalize.html", {'meeting':meeting,})
|
||||
|
||||
@role_required('Secretariat')
|
||||
def proceedings_acknowledgements(request, num=None):
|
||||
|
||||
'''Display Acknowledgements for meeting'''
|
||||
meeting = get_meeting(num)
|
||||
if meeting.number < 95:
|
||||
if not num.isdigit():
|
||||
raise Http404
|
||||
if int(meeting.number) < settings.NEW_PROCEEDINGS_START:
|
||||
return HttpResponseRedirect( 'https://www.ietf.org/proceedings/%s/acknowledgement.html' % num )
|
||||
return render(request, "meeting/proceedings_acknowledgements.html", {
|
||||
'meeting': meeting,
|
||||
})
|
||||
|
||||
@role_required('Secretariat')
|
||||
def proceedings_attendees(request, num=None):
|
||||
'''Display list of meeting attendees'''
|
||||
meeting = get_meeting(num)
|
||||
if not num.isdigit():
|
||||
raise Http404
|
||||
if int(meeting.number) < settings.NEW_PROCEEDINGS_START:
|
||||
return HttpResponseRedirect( 'https://www.ietf.org/proceedings/%s/attendees.html' % num )
|
||||
overview_template = '/meeting/proceedings/%s/attendees.html' % meeting.number
|
||||
try:
|
||||
template = render_to_string(overview_template, {})
|
||||
except TemplateDoesNotExist:
|
||||
raise Http404
|
||||
return render(request, "meeting/proceedings_attendees.html", {
|
||||
'meeting': meeting,
|
||||
'template': template,
|
||||
})
|
||||
|
||||
def proceedings_overview(request, num=None):
|
||||
'''Display Overview for given meeting'''
|
||||
meeting = get_meeting(num)
|
||||
if meeting.number < 95:
|
||||
if not num.isdigit():
|
||||
raise Http404
|
||||
if int(meeting.number) < settings.NEW_PROCEEDINGS_START:
|
||||
return HttpResponseRedirect( 'https://www.ietf.org/proceedings/%s/overview.html' % num )
|
||||
overview_template = '/meeting/proceedings/%s/overview.rst' % meeting.number
|
||||
template = render_to_string(overview_template, {})
|
||||
|
||||
try:
|
||||
template = render_to_string(overview_template, {})
|
||||
except TemplateDoesNotExist:
|
||||
raise Http404
|
||||
return render(request, "meeting/proceedings_overview.html", {
|
||||
'meeting': meeting,
|
||||
'template': template,
|
||||
})
|
||||
|
||||
@cache_page( 60 * 60 )
|
||||
def proceedings_progress_report(request, num=None):
|
||||
'''Display Progress Report (stats since last meeting)'''
|
||||
meeting = get_meeting(num)
|
||||
if not num.isdigit():
|
||||
raise Http404
|
||||
if int(meeting.number) < settings.NEW_PROCEEDINGS_START:
|
||||
return HttpResponseRedirect( 'https://www.ietf.org/proceedings/%s/progress-report.html' % num )
|
||||
sdate = meeting.previous_meeting().date
|
||||
edate = meeting.date
|
||||
context = get_progress_stats(sdate,edate)
|
||||
context['meeting'] = meeting
|
||||
return render(request, "meeting/proceedings_progress_report.html", context)
|
||||
|
||||
class OldUploadRedirect(RedirectView):
|
||||
def get_redirect_url(self, **kwargs):
|
||||
return reverse_lazy('ietf.meeting.views.session_details',kwargs=self.kwargs)
|
||||
|
|
|
@ -85,8 +85,6 @@ class SecrMeetingTestCase(TestCase):
|
|||
response = self.client.post(url, post_data, follow=True)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(Meeting.objects.count(),count + 1)
|
||||
meeting = Meeting.objects.order_by('id').last()
|
||||
self.assertEqual(meeting.overview.path,'/meeting/proceedings/%s/overview.rst' % meeting.number)
|
||||
|
||||
def test_edit_meeting(self):
|
||||
"Edit Meeting"
|
||||
|
|
|
@ -14,7 +14,6 @@ from django.shortcuts import render_to_response, get_object_or_404, redirect
|
|||
from django.template import RequestContext
|
||||
from django.utils.functional import curry
|
||||
|
||||
from ietf.dbtemplate.models import DBTemplate
|
||||
from ietf.ietfauth.utils import role_required
|
||||
from ietf.utils.mail import send_mail
|
||||
from ietf.meeting.helpers import get_meeting, make_materials_directories
|
||||
|
@ -318,15 +317,6 @@ def add(request):
|
|||
# Create Physical new meeting directory and subdirectories
|
||||
make_materials_directories(meeting)
|
||||
|
||||
# Make copy of IETF Overview template
|
||||
template = DBTemplate.objects.get(path='/meeting/proceedings/defaults/overview.rst')
|
||||
template.id = None
|
||||
template.path = '/meeting/proceedings/%s/overview.rst' % (meeting.number)
|
||||
template.title = 'IETF %s Proceedings Overview' % (meeting.number)
|
||||
template.save()
|
||||
meeting.overview = template
|
||||
meeting.save()
|
||||
|
||||
messages.success(request, 'The Meeting was created successfully!')
|
||||
return redirect('meetings')
|
||||
else:
|
||||
|
|
|
@ -106,97 +106,67 @@ def mycomp(timeslot):
|
|||
|
||||
def get_progress_stats(sdate,edate):
|
||||
'''
|
||||
This function takes a date range and produces a dictionary of statistics / objects for use
|
||||
in a progress report. Generally the end date will be the date of the last meeting
|
||||
This function takes a date range and produces a dictionary of statistics / objects for
|
||||
use in a progress report. Generally the end date will be the date of the last meeting
|
||||
and the start date will be the date of the meeting before that.
|
||||
'''
|
||||
data = {}
|
||||
data['sdate'] = sdate
|
||||
data['edate'] = edate
|
||||
|
||||
# Activty Report Section
|
||||
new_docs = Document.objects.filter(type='draft').filter(docevent__type='new_revision',
|
||||
docevent__newrevisiondocevent__rev='00',
|
||||
docevent__time__gte=sdate,
|
||||
docevent__time__lt=edate)
|
||||
data['new'] = new_docs.count()
|
||||
data['updated'] = 0
|
||||
data['updated_more'] = 0
|
||||
for d in new_docs:
|
||||
updates = d.docevent_set.filter(type='new_revision',time__gte=sdate,time__lt=edate).count()
|
||||
if updates > 1:
|
||||
data['updated'] += 1
|
||||
if updates > 2:
|
||||
data['updated_more'] +=1
|
||||
|
||||
# calculate total documents updated, not counting new, rev=00
|
||||
result = set()
|
||||
events = DocEvent.objects.filter(doc__type='draft',time__gte=sdate,time__lt=edate)
|
||||
for e in events.filter(type='new_revision').exclude(newrevisiondocevent__rev='00'):
|
||||
result.add(e.doc)
|
||||
data['total_updated'] = len(result)
|
||||
|
||||
# calculate sent last call
|
||||
data['last_call'] = events.filter(type='sent_last_call').count()
|
||||
data['actions_count'] = events.filter(type='iesg_approved').count()
|
||||
data['last_calls_count'] = events.filter(type='sent_last_call').count()
|
||||
new_draft_events = events.filter(newrevisiondocevent__rev='00')
|
||||
new_drafts = list(set([ e.doc_id for e in new_draft_events ]))
|
||||
data['new_drafts_count'] = len(new_drafts)
|
||||
data['new_drafts_updated_count'] = events.filter(doc__in=new_drafts,newrevisiondocevent__rev='01').count()
|
||||
data['new_drafts_updated_more_count'] = events.filter(doc__in=new_drafts,newrevisiondocevent__rev='02').count()
|
||||
|
||||
# calculate approved
|
||||
data['approved'] = events.filter(type='iesg_approved').count()
|
||||
update_events = events.filter(type='new_revision').exclude(doc__in=new_drafts)
|
||||
data['updated_drafts_count'] = len(set([ e.doc_id for e in update_events ]))
|
||||
|
||||
# get 4 weeks
|
||||
ff1_date = edate - datetime.timedelta(days=28)
|
||||
ff_docs = Document.objects.filter(type='draft').filter(docevent__type='new_revision',
|
||||
docevent__newrevisiondocevent__rev='00',
|
||||
docevent__time__gte=ff1_date,
|
||||
docevent__time__lt=edate)
|
||||
ff_new_count = ff_docs.count()
|
||||
ff_new_percent = format(ff_new_count / float(data['new']),'.0%')
|
||||
# Calculate Final Four Weeks stats (ffw)
|
||||
ffwdate = edate - datetime.timedelta(days=28)
|
||||
ffw_new_count = events.filter(time__gte=ffwdate,newrevisiondocevent__rev='00').count()
|
||||
try:
|
||||
ffw_new_percent = format(ffw_new_count / float(data['new_drafts_count']),'.0%')
|
||||
except ZeroDivisionError:
|
||||
ffw_new_percent = 0
|
||||
|
||||
# calculate total documents updated in final four weeks, not counting new, rev=00
|
||||
result = set()
|
||||
events = DocEvent.objects.filter(doc__type='draft',time__gte=ff1_date,time__lt=edate)
|
||||
for e in events.filter(type='new_revision').exclude(newrevisiondocevent__rev='00'):
|
||||
result.add(e.doc)
|
||||
ff_update_count = len(result)
|
||||
ff_update_percent = format(ff_update_count / float(data['total_updated']),'.0%')
|
||||
data['ffw_new_count'] = ffw_new_count
|
||||
data['ffw_new_percent'] = ffw_new_percent
|
||||
|
||||
data['ff_new_count'] = ff_new_count
|
||||
data['ff_new_percent'] = ff_new_percent
|
||||
data['ff_update_count'] = ff_update_count
|
||||
data['ff_update_percent'] = ff_update_percent
|
||||
ffw_update_events = events.filter(time__gte=ffwdate,type='new_revision').exclude(doc__in=new_drafts)
|
||||
ffw_update_count = len(set([ e.doc_id for e in ffw_update_events ]))
|
||||
try:
|
||||
ffw_update_percent = format(ffw_update_count / float(data['updated_drafts_count']),'.0%')
|
||||
except ZeroDivisionError:
|
||||
ffw_update_percent = 0
|
||||
|
||||
# Progress Report Section
|
||||
data['docevents'] = DocEvent.objects.filter(doc__type='draft',time__gte=sdate,time__lt=edate)
|
||||
data['action_events'] = data['docevents'].filter(type='iesg_approved')
|
||||
data['lc_events'] = data['docevents'].filter(type='sent_last_call')
|
||||
data['ffw_update_count'] = ffw_update_count
|
||||
data['ffw_update_percent'] = ffw_update_percent
|
||||
|
||||
data['new_groups'] = Group.objects.filter(type='wg',
|
||||
groupevent__changestategroupevent__state='active',
|
||||
groupevent__time__gte=sdate,
|
||||
groupevent__time__lt=edate)
|
||||
rfcs = events.filter(type='published_rfc')
|
||||
data['rfcs'] = rfcs.select_related('doc').select_related('doc__group').select_related('doc__intended_std_level')
|
||||
|
||||
data['concluded_groups'] = Group.objects.filter(type='wg',
|
||||
groupevent__changestategroupevent__state='conclude',
|
||||
groupevent__time__gte=sdate,
|
||||
groupevent__time__lt=edate)
|
||||
data['counts'] = {'std':rfcs.filter(doc__intended_std_level__in=('ps','ds','std')).count(),
|
||||
'bcp':rfcs.filter(doc__intended_std_level='bcp').count(),
|
||||
'exp':rfcs.filter(doc__intended_std_level='exp').count(),
|
||||
'inf':rfcs.filter(doc__intended_std_level='inf').count()}
|
||||
|
||||
data['new_docs'] = Document.objects.filter(type='draft').filter(docevent__type='new_revision',
|
||||
docevent__time__gte=sdate,
|
||||
docevent__time__lt=edate).distinct()
|
||||
data['new_groups'] = Group.objects.filter(
|
||||
type='wg',
|
||||
groupevent__changestategroupevent__state='active',
|
||||
groupevent__time__gte=sdate,
|
||||
groupevent__time__lt=edate)
|
||||
|
||||
data['rfcs'] = DocEvent.objects.filter(type='published_rfc',
|
||||
doc__type='draft',
|
||||
time__gte=sdate,
|
||||
time__lt=edate)
|
||||
|
||||
# attach the ftp URL for use in the template
|
||||
for event in data['rfcs']:
|
||||
num = get_rfc_num(event.doc)
|
||||
event.ftp_url = 'ftp://ftp.ietf.org/rfc/rfc%s.txt' % num
|
||||
|
||||
data['counts'] = {'std':data['rfcs'].filter(doc__intended_std_level__in=('ps','ds','std')).count(),
|
||||
'bcp':data['rfcs'].filter(doc__intended_std_level='bcp').count(),
|
||||
'exp':data['rfcs'].filter(doc__intended_std_level='exp').count(),
|
||||
'inf':data['rfcs'].filter(doc__intended_std_level='inf').count()}
|
||||
data['concluded_groups'] = Group.objects.filter(
|
||||
type='wg',
|
||||
groupevent__changestategroupevent__state='conclude',
|
||||
groupevent__time__gte=sdate,
|
||||
groupevent__time__lt=edate)
|
||||
|
||||
return data
|
||||
|
||||
|
|
|
@ -599,7 +599,8 @@ SECR_INTERIM_LISTING_DIR = '/a/www/www6/meeting/interim'
|
|||
SECR_MAX_UPLOAD_SIZE = 40960000
|
||||
SECR_PROCEEDINGS_DIR = '/a/www/www6s/proceedings/'
|
||||
SECR_PPT2PDF_COMMAND = ['/usr/bin/soffice','--headless','--convert-to','pdf','--outdir']
|
||||
|
||||
REGISTRATION_ATTENDEES_BASE_URL = 'https://ietf.org/registration/attendees/'
|
||||
NEW_PROCEEDINGS_START = 95
|
||||
USE_ETAGS=True
|
||||
|
||||
PRODUCTION_TIMEZONE = "America/Los_Angeles"
|
||||
|
|
|
@ -544,6 +544,12 @@ ul.errorlist {
|
|||
color: #555;
|
||||
}
|
||||
|
||||
/* === Proceedings ===================================================== */
|
||||
ul.progress-section {
|
||||
list-style-type: none;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
/* === Font-Awesome ========================================================= */
|
||||
|
||||
.btn .fa-stack { width: 1em; height: 1em; }
|
||||
|
|
|
@ -33,13 +33,15 @@
|
|||
{% load cache %}
|
||||
{% cache 900 ietf_meeting_proceedings meeting.number cache_version %}
|
||||
|
||||
{% if meeting.proceedings_final %}
|
||||
<h2 class="anchor-target" id="introduction">Introduction</h2>
|
||||
<div>
|
||||
<a href="{% url 'ietf.meeting.views.proceedings_acknowledgements' num=meeting.number %}">Acknowledgements</a><br>
|
||||
<a href="{% url 'ietf.meeting.views.proceedings_overview' num=meeting.number %}">IETF Overview</a><br>
|
||||
<a href="#">Progress Report</a><br>
|
||||
<a href="#">Attendees</a><br>
|
||||
<a href="{% url 'ietf.meeting.views.proceedings_progress_report' num=meeting.number %}">Progress Report</a><br>
|
||||
<a href="{% url 'ietf.meeting.views.proceedings_attendees' num=meeting.number %}">Attendees</a><br>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% with "True" as show_agenda %}
|
||||
<!-- Plenaries -->
|
||||
|
|
14
ietf/templates/meeting/proceedings_attendees.html
Normal file
14
ietf/templates/meeting/proceedings_attendees.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin markup_tags %}
|
||||
|
||||
{% block title %}IETF {{ meeting.number }} Proceedings {% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
<h1><a href="{% url 'ietf.meeting.views.proceedings' num=meeting.number %}">IETF {{ meeting.number }} Proceedings</a></h1>
|
||||
<h2>Attendee List of IETF {{ meeting.number }} Meeting</h2>
|
||||
|
||||
{{ template|safe }}
|
||||
|
||||
{% endblock %}
|
18
ietf/templates/meeting/proceedings_attendees_table.html
Normal file
18
ietf/templates/meeting/proceedings_attendees_table.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
<table id="id_attendees" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Last Name</th>
|
||||
<th>First Name</th>
|
||||
<th>Organization</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for attendee in attendees %}
|
||||
<tr>
|
||||
<td>{{ attendee.LastName }}</td>
|
||||
<td>{{ attendee.FirstName }}</td>
|
||||
<td>{{ attendee.Company }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
53
ietf/templates/meeting/proceedings_progress_report.html
Normal file
53
ietf/templates/meeting/proceedings_progress_report.html
Normal file
|
@ -0,0 +1,53 @@
|
|||
{% extends "base.html" %}
|
||||
{% load ams_filters %}
|
||||
|
||||
{% block title %}IETF {{ meeting.number }} Proceedings - Progress Report{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1><a href="{% url 'ietf.meeting.views.proceedings' num=meeting.number %}">IETF {{ meeting.number }} Proceedings</a></h1>
|
||||
<h2>IETF Progress Report</h2>
|
||||
|
||||
<h4>{{ sdate|date:"d-F-y" }} to {{ edate|date:"d-F-y" }}</h4>
|
||||
|
||||
<ul class="progress-section">
|
||||
<li>{{ actions_count }} IESG Protocol and Document Actions this period</li>
|
||||
<li>{{ last_calls_count }} IESG Last Calls issued to the IETF this period</li>
|
||||
<li></li>
|
||||
<li>{{ new_drafts_count|stringformat:"3s" }} New I-Ds ({{ new_drafts_updated_count }} of which were updated, some ({{ new_drafts_updated_more_count }}) more than once)</li>
|
||||
<li>{{ updated_drafts_count|stringformat:"3s" }} I-Ds were updated (Some more than once)</li>
|
||||
<li></li>
|
||||
<li><h4>In the final 4 weeks before meeting</h4></li>
|
||||
<li>{{ ffw_new_count|stringformat:"3s" }} New I-Ds were received - {{ ffw_new_percent }} of total newbies since last meeting</li>
|
||||
<li>{{ ffw_update_count|stringformat:"3s" }} I-Ds were updated - {{ ffw_update_percent }} of total updated since last meeting</li>
|
||||
</ul>
|
||||
<h4>{{ new_groups.count }} New Working Group(s) formed this period</h4>
|
||||
<ul class="progress-section">
|
||||
{% for group in new_groups %}
|
||||
<li>{{ group.name }} ({{ group.acronym }})</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h4>{{ concluded_groups.count }} Working Group(s) concluded this period</h4>
|
||||
<ul class="progress-section">
|
||||
{% for group in concluded_groups %}
|
||||
<li>{{ group.name }} ({{ group.acronym }})</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h4>{{ rfcs.count }} RFCs published this period</h4>
|
||||
<p>{{ counts.std }} Standards Track; {{ counts.bcp }} BCP; {{ counts.exp }} Experimental; {{ counts.inf }} Informational</p>
|
||||
|
||||
<table class="table">
|
||||
{% for rfc in rfcs %}
|
||||
<tr>
|
||||
<td><a href="{{ rfc.doc.get_absolute_url }}">{{ rfc.doc.canonical_name|upper }}</a></td>
|
||||
<td>{{ rfc.doc.intended_std_level.name|abbr_status }}</td>
|
||||
<td>({{ rfc.doc.group.acronym }})</td>
|
||||
<td>{{ rfc.time|date:"F Y" }}</td>
|
||||
<td>{{ rfc.doc.title }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
|
@ -18,6 +18,7 @@ html5lib>=0.90,<0.99999999 # ietf.utils.html needs a rewrite for html5lib 1.x --
|
|||
jsonfield>=1.0.3 # for SubmissionCheck. This is https://github.com/bradjasper/django-jsonfield/.
|
||||
#lxml>=3.4.0 # from PyQuery;
|
||||
mimeparse>=0.1.3 # from TastyPie
|
||||
mock>=2.0.0
|
||||
MySQL-python>=1.2.5
|
||||
pathlib>=1.0
|
||||
Pillow>=3.0
|
||||
|
|
Loading…
Reference in a new issue