Adds a meetings tab to the group information page. Links to minutes, agendas, and materials for each session at each meeting. Improves the UI for the session materials page. Commit ready for merge.
- Legacy-Id: 10719
This commit is contained in:
commit
7d43d3ada4
|
@ -36,6 +36,7 @@ import os
|
|||
import itertools
|
||||
import re
|
||||
from tempfile import mkstemp
|
||||
import datetime
|
||||
from collections import OrderedDict
|
||||
|
||||
from django.shortcuts import render, redirect
|
||||
|
@ -333,6 +334,8 @@ def construct_group_menu_context(request, group, selected, group_type, others):
|
|||
entries.append(("About", urlreverse("group_about", kwargs=kwargs)))
|
||||
if group.features.has_materials and get_group_materials(group).exists():
|
||||
entries.append(("Materials", urlreverse("ietf.group.info.materials", kwargs=kwargs)))
|
||||
if group.type_id in ('rg','wg'):
|
||||
entries.append(("Meetings", urlreverse("ietf.group.info.meetings", kwargs=kwargs)))
|
||||
entries.append(("Email expansions", urlreverse("ietf.group.info.email", kwargs=kwargs)))
|
||||
entries.append(("History", urlreverse("ietf.group.info.history", kwargs=kwargs)))
|
||||
if group.features.has_documents:
|
||||
|
@ -724,3 +727,47 @@ def email_aliases(request, acronym=None, group_type=None):
|
|||
|
||||
return render(request,'group/email_aliases.html',{'aliases':aliases,'ietf_domain':settings.IETF_DOMAIN,'group':group})
|
||||
|
||||
def meetings(request, acronym=None, group_type=None):
|
||||
group = get_group_or_404(acronym,group_type) if acronym else None
|
||||
|
||||
four_years_ago = datetime.datetime.now()-datetime.timedelta(days=4*365)
|
||||
|
||||
sessions = group.session_set.filter(status__in=['sched','schedw','appr','canceled'],meeting__date__gt=four_years_ago)
|
||||
|
||||
def sort_key(session):
|
||||
if session.meeting.type.slug=='ietf':
|
||||
official_sessions = session.timeslotassignments.filter(schedule=session.meeting.agenda)
|
||||
if official_sessions:
|
||||
return official_sessions.first().timeslot.time
|
||||
elif session.meeting.date:
|
||||
return datetime.datetime.combine(session.meeting.date,datetime.datetime.min.time())
|
||||
else:
|
||||
return session.requested
|
||||
else:
|
||||
# TODO: use timeslots for interims once they have them
|
||||
return datetime.datetime.combine(session.meeting.date,datetime.datetime.min.time())
|
||||
|
||||
for s in sessions:
|
||||
s.time=sort_key(s)
|
||||
|
||||
sessions = sorted(sessions,key=lambda s:s.time,reverse=True)
|
||||
|
||||
today = datetime.date.today()
|
||||
future = []
|
||||
in_progress = []
|
||||
past = []
|
||||
for s in sessions:
|
||||
if s.meeting.date > today:
|
||||
future.append(s)
|
||||
elif s.meeting.end_date() >= today:
|
||||
in_progress.append(s)
|
||||
else:
|
||||
past.append(s)
|
||||
|
||||
return render(request,'group/meetings.html',
|
||||
construct_group_menu_context(request, group, "meetings", group_type, {
|
||||
'group':group,
|
||||
'future':future,
|
||||
'in_progress':in_progress,
|
||||
'past':past,
|
||||
}))
|
||||
|
|
|
@ -22,6 +22,8 @@ from ietf.utils.test_utils import TestCase, unicontent
|
|||
from ietf.utils.mail import outbox, empty_outbox
|
||||
from ietf.utils.test_data import make_test_data
|
||||
from ietf.utils.test_utils import login_testing_unauthorized
|
||||
from ietf.group.factories import GroupFactory
|
||||
from ietf.meeting.factories import SessionFactory
|
||||
|
||||
class GroupPagesTests(TestCase):
|
||||
def setUp(self):
|
||||
|
@ -988,3 +990,29 @@ class AjaxTests(TestCase):
|
|||
mars_wg = Group.objects.get(acronym="mars")
|
||||
self.assertEqual(mars_wg_data["name"], mars_wg.name)
|
||||
|
||||
class MeetingInfoTests(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.group = GroupFactory.create(type_id='wg')
|
||||
today = datetime.date.today()
|
||||
SessionFactory.create(meeting__type_id='ietf',group=self.group,meeting__date=today-datetime.timedelta(days=90))
|
||||
self.inprog = SessionFactory.create(meeting__type_id='ietf',group=self.group,meeting__date=today-datetime.timedelta(days=1))
|
||||
SessionFactory.create(meeting__type_id='ietf',group=self.group,meeting__date=today+datetime.timedelta(days=90))
|
||||
SessionFactory.create(meeting__type_id='interim',group=self.group,meeting__date=today+datetime.timedelta(days=45))
|
||||
|
||||
|
||||
def test_meeting_info(self):
|
||||
url = urlreverse('ietf.group.info.meetings',kwargs={'acronym':self.group.acronym})
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
q = PyQuery(response.content)
|
||||
self.assertTrue(q('#inprogressmeets'))
|
||||
self.assertTrue(q('#futuremeets'))
|
||||
self.assertTrue(q('#pastmeets'))
|
||||
|
||||
self.group.session_set.filter(id=self.inprog.id).delete()
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
q = PyQuery(response.content)
|
||||
self.assertFalse(q('#inprogressmeets'))
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ urlpatterns = patterns('',
|
|||
(r'^chartering/create/(?P<group_type>(wg|rg))/$', 'ietf.group.edit.edit', {'action': "charter"}, "group_create"),
|
||||
(r'^concluded/$', 'ietf.group.info.concluded_groups'),
|
||||
(r'^email-aliases/$', 'ietf.group.info.email_aliases'),
|
||||
|
||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/$', 'ietf.group.info.group_home', None, "group_home"),
|
||||
(r'^(?P<acronym>[a-zA-Z0-9-._]+)/', include('ietf.group.urls_info_details')),
|
||||
)
|
||||
|
|
|
@ -10,6 +10,7 @@ urlpatterns = patterns('',
|
|||
(r'^history/$','ietf.group.info.history'),
|
||||
(r'^email/$', 'ietf.group.info.email'),
|
||||
(r'^deps/(?P<output_type>[\w-]+)/$', 'ietf.group.info.dependencies'),
|
||||
(r'^meetings/$', 'ietf.group.info.meetings'),
|
||||
(r'^init-charter/', 'ietf.group.edit.submit_initial_charter'),
|
||||
(r'^edit/$', 'ietf.group.edit.edit', {'action': "edit"}, "group_edit"),
|
||||
(r'^conclude/$', 'ietf.group.edit.conclude'),
|
||||
|
|
99
ietf/meeting/factories.py
Normal file
99
ietf/meeting/factories.py
Normal file
|
@ -0,0 +1,99 @@
|
|||
import factory
|
||||
import random
|
||||
import datetime
|
||||
|
||||
from django.db.models import Max
|
||||
|
||||
from ietf.meeting.models import Meeting, Session, Schedule, TimeSlot
|
||||
from ietf.group.factories import GroupFactory
|
||||
from ietf.person.factories import PersonFactory
|
||||
|
||||
class MeetingFactory(factory.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = Meeting
|
||||
|
||||
type_id = factory.Iterator(['ietf','interim'])
|
||||
date = datetime.date(2010,1,1)+datetime.timedelta(days=random.randint(0,3652))
|
||||
city = factory.Faker('city')
|
||||
country = factory.Faker('country_code')
|
||||
time_zone = factory.Faker('timezone')
|
||||
idsubmit_cutoff_day_offset_00 = 13
|
||||
idsubmit_cutoff_day_offset_01 = 13
|
||||
idsubmit_cutoff_time_utc = datetime.timedelta(0, 86399)
|
||||
idsubmit_cutoff_warning_days = 21
|
||||
venue_name = factory.Faker('sentence')
|
||||
venue_addr = factory.Faker('address')
|
||||
break_area = factory.Faker('sentence')
|
||||
reg_area = factory.Faker('sentence')
|
||||
|
||||
@factory.lazy_attribute_sequence
|
||||
def number(self,n):
|
||||
if self.type_id == 'ietf':
|
||||
if Meeting.objects.filter(type='ietf').exists():
|
||||
return '%02d'%(int(Meeting.objects.filter(type='ietf').aggregate(Max('number'))['number__max'])+1)
|
||||
else:
|
||||
return '%02d'%(n+80)
|
||||
else:
|
||||
return 'interim-%d-%s-%d'%(self.date.year,GroupFactory().acronym,n)
|
||||
|
||||
@factory.post_generation
|
||||
def populate_agenda(self, create, extracted, **kwargs):
|
||||
'''
|
||||
Create a default agenda, unless the factory is called
|
||||
with populate_agenda=False
|
||||
'''
|
||||
if extracted is None:
|
||||
extracted = True
|
||||
if create and extracted:
|
||||
for x in range(3):
|
||||
TimeSlotFactory(meeting=self)
|
||||
self.agenda = ScheduleFactory(meeting=self)
|
||||
self.save()
|
||||
|
||||
|
||||
class SessionFactory(factory.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = Session
|
||||
|
||||
meeting = factory.SubFactory(MeetingFactory)
|
||||
type_id='session'
|
||||
group = factory.SubFactory(GroupFactory)
|
||||
requested_by = factory.SubFactory(PersonFactory)
|
||||
status_id='sched'
|
||||
|
||||
@factory.post_generation
|
||||
def add_to_schedule(self, create, extracted, **kwargs):
|
||||
'''
|
||||
Put this session in a timeslot unless the factory is called
|
||||
with add_to_schedule=False
|
||||
'''
|
||||
if extracted is None:
|
||||
extracted = True
|
||||
if create and extracted:
|
||||
ts = self.meeting.timeslot_set.all()
|
||||
self.timeslotassignments.create(timeslot=ts[random.randrange(len(ts))],schedule=self.meeting.agenda)
|
||||
|
||||
class ScheduleFactory(factory.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = Schedule
|
||||
|
||||
meeting = factory.SubFactory(MeetingFactory)
|
||||
name = factory.Faker('text',max_nb_chars=16)
|
||||
owner = factory.SubFactory(PersonFactory)
|
||||
|
||||
class TimeSlotFactory(factory.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = TimeSlot
|
||||
|
||||
meeting = factory.SubFactory(MeetingFactory)
|
||||
type_id = 'session'
|
||||
|
||||
@factory.lazy_attribute
|
||||
def time(self):
|
||||
return datetime.datetime.combine(self.meeting.date,datetime.time(11,0))
|
||||
|
||||
@factory.lazy_attribute
|
||||
def duration(self):
|
||||
return datetime.timedelta(minutes=30+random.randrange(9)*15)
|
||||
|
||||
|
23
ietf/meeting/migrations/0016_schedule_ietf88_and_89.py
Normal file
23
ietf/meeting/migrations/0016_schedule_ietf88_and_89.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
Session = apps.get_model('meeting','Session')
|
||||
assert(Session.objects.filter(meeting__number__in=['88','89'],group__type__in=['ag','iab','rg','wg'],status_id='sched').count() == 0)
|
||||
Session.objects.filter(meeting__number__in=['88','89'],group__type__in=['ag','iab','rg','wg'],status_id='schedw').update(status_id='sched')
|
||||
|
||||
def reverse(apps, schema_editor):
|
||||
Session = apps.get_model('meeting','Session')
|
||||
Session.objects.filter(meeting__number__in=['88','89'],group__type__in=['ag','iab','rg','wg'],status_id='sched').update(status_id='schedw')
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('meeting', '0015_auto_20151102_1845'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward,reverse),
|
||||
]
|
27
ietf/meeting/migrations/0017_schedule_approved_interims.py
Normal file
27
ietf/meeting/migrations/0017_schedule_approved_interims.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
from collections import Counter
|
||||
|
||||
affected = ['interim-2010-drinks-1','interim-2010-core-1','interim-2010-behave-1','interim-2010-siprec-1','interim-2010-cuss-1','interim-2010-iri-1','interim-2010-pcp-1','interim-2010-geopriv-1','interim-2010-soc-1','interim-2010-precis-1','interim-2010-mptcp-1','interim-2010-roll-1','interim-2011-sipclf-1','interim-2011-ipsecme-1','interim-2011-siprec-1','interim-2011-alto-1','interim-2011-xmpp-1','interim-2011-precis-1','interim-2011-nfsv4-1','interim-2011-pcp-1','interim-2011-clue-1','interim-2011-oauth-1','interim-2011-rtcweb-1','interim-2011-drinks-1','interim-2011-atoca-1','interim-2011-cuss-1','interim-2011-softwire-1','interim-2011-ppsp-1','interim-2011-homenet-1','interim-2011-mptcp-1','interim-2012-rtcweb-1','interim-2012-drinks-1','interim-2012-sidr-1','interim-2012-clue-1','interim-2012-krb-wg-1','interim-2012-behave-1','interim-2012-bfcpbis-1','interim-2012-mboned-1']
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
Session = apps.get_model('meeting','Session')
|
||||
assert( Counter(Session.objects.filter(meeting__number__in=affected).values_list('status',flat=True)) == Counter({u'appr':38}) )
|
||||
Session.objects.filter(meeting__number__in=affected).update(status_id='sched')
|
||||
|
||||
def reverse(apps, schema_editor):
|
||||
Session = apps.get_model('meeting','Session')
|
||||
Session.objects.filter(meeting__number__in=affected).update(status_id='appr')
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('meeting', '0016_schedule_ietf88_and_89'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward,reverse),
|
||||
]
|
|
@ -96,7 +96,12 @@ class Meeting(models.Model):
|
|||
return self.date + datetime.timedelta(days=offset)
|
||||
|
||||
def end_date(self):
|
||||
return self.get_meeting_date(5)
|
||||
if self.type.slug == 'ietf':
|
||||
return self.get_meeting_date(5)
|
||||
else:
|
||||
# TODO: Once interims have timeslots assigned,
|
||||
# look for the last ending timeslot instead
|
||||
return self.date
|
||||
|
||||
def get_00_cutoff(self):
|
||||
start_date = datetime.datetime(year=self.date.year, month=self.date.month, day=self.date.day, tzinfo=pytz.utc)
|
||||
|
|
|
@ -61,10 +61,6 @@ urlpatterns = patterns('',
|
|||
(r'^(?P<num>\d+)/session/(?P<sessionid>\d+)/constraints.json', ajax.session_constraints),
|
||||
|
||||
(r'^(?P<num>\d+)/session/(?P<acronym>[A-Za-z0-9_\-\+]+)/$', views.session_details),
|
||||
(r'^(?P<num>\d+)/session/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<seq>\d+)/$', views.session_details),
|
||||
(r'^(?P<num>\d+)/session/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<week_day>[a-zA-Z]+)/$', views.session_details),
|
||||
(r'^(?P<num>\d+)/session/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/$', views.session_details),
|
||||
(r'^(?P<num>\d+)/session/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/(?P<seq>\d+)/$', views.session_details),
|
||||
|
||||
(r'^(?P<num>\d+)/constraint/(?P<constraintid>\d+).json', ajax.constraint_json),
|
||||
(r'^(?P<num>\d+).json$', ajax.meeting_json),
|
||||
|
|
|
@ -825,30 +825,13 @@ def meeting_requests(request, num=None):
|
|||
{"meeting": meeting, "sessions":sessions,
|
||||
"groups_not_meeting": groups_not_meeting})
|
||||
|
||||
def session_details(request, num, acronym, date=None, week_day=None, seq=None):
|
||||
def session_details(request, num, acronym ):
|
||||
meeting = get_meeting(num)
|
||||
sessions = Session.objects.filter(meeting=meeting,group__acronym=acronym,type__in=['session','plenary','other'])
|
||||
|
||||
if not sessions:
|
||||
sessions = Session.objects.filter(meeting=meeting,short=acronym)
|
||||
|
||||
if date:
|
||||
if len(date)==15:
|
||||
start = datetime.datetime.strptime(date,"%Y-%m-%d-%H%M")
|
||||
sessions = sessions.filter(timeslotassignments__schedule=meeting.agenda,timeslotassignments__timeslot__time=start)
|
||||
else:
|
||||
start = datetime.datetime.strptime(date,"%Y-%m-%d").date()
|
||||
end = start+datetime.timedelta(days=1)
|
||||
sessions = sessions.filter(timeslotassignments__schedule=meeting.agenda,timeslotassignments__timeslot__time__range=(start,end))
|
||||
|
||||
if week_day:
|
||||
try:
|
||||
dow = ['sun','mon','tue','wed','thu','fri','sat'].index(week_day.lower()[:3]) + 1
|
||||
except ValueError:
|
||||
raise Http404
|
||||
sessions = sessions.filter(timeslotassignments__schedule=meeting.agenda,timeslotassignments__timeslot__time__week_day=dow)
|
||||
|
||||
|
||||
def sort_key(session):
|
||||
official_sessions = session.timeslotassignments.filter(schedule=session.meeting.agenda)
|
||||
if official_sessions:
|
||||
|
@ -858,34 +841,19 @@ def session_details(request, num, acronym, date=None, week_day=None, seq=None):
|
|||
|
||||
sessions = sorted(sessions,key=sort_key)
|
||||
|
||||
if seq:
|
||||
iseq = int(seq) - 1
|
||||
if not iseq in range(0,len(sessions)):
|
||||
raise Http404
|
||||
else:
|
||||
sessions= [sessions[iseq]]
|
||||
|
||||
if not sessions:
|
||||
raise Http404
|
||||
|
||||
if len(sessions)==1:
|
||||
session = sessions[0]
|
||||
scheduled_time = "Not yet scheduled"
|
||||
for session in sessions:
|
||||
|
||||
ss = session.timeslotassignments.filter(schedule=meeting.agenda).order_by('timeslot__time')
|
||||
if ss:
|
||||
scheduled_time = ','.join(x.timeslot.time.strftime("%A %b-%d %H%M") for x in ss)
|
||||
session.time = ', '.join(x.timeslot.time.strftime("%A %b-%d %H%M") for x in ss) if ss else 'Not yet scheduled'
|
||||
|
||||
# TODO FIXME Deleted materials shouldn't be in the sessionpresentation_set
|
||||
filtered_sessionpresentation_set = [p for p in session.sessionpresentation_set.all() if p.document.get_state_slug(p.document.type_id)!='deleted']
|
||||
return render(request, "meeting/session_details.html",
|
||||
{ 'session':sessions[0] ,
|
||||
'meeting' :meeting ,
|
||||
'acronym' :acronym,
|
||||
'time': scheduled_time,
|
||||
'filtered_sessionpresentation_set': filtered_sessionpresentation_set
|
||||
})
|
||||
else:
|
||||
return render(request, "meeting/session_list.html",
|
||||
{ 'sessions':sessions ,
|
||||
'meeting' :meeting ,
|
||||
'acronym' :acronym,
|
||||
})
|
||||
session.filtered_sessionpresentation_set = [p for p in session.sessionpresentation_set.all() if p.document.get_state_slug(p.document.type_id)!='deleted']
|
||||
|
||||
return render(request, "meeting/session_details.html",
|
||||
{ 'sessions':sessions ,
|
||||
'meeting' :meeting ,
|
||||
'acronym' :acronym,
|
||||
})
|
||||
|
|
27
ietf/templates/group/meetings-row.html
Normal file
27
ietf/templates/group/meetings-row.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<table class="table table-condensed table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-2"></th>
|
||||
<th class="col-md-2"></th>
|
||||
<th class="col-md-1"></th>
|
||||
<th class="col-md-1"></th>
|
||||
<th class="col-md-6"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for s in sessions %}
|
||||
<tr>
|
||||
<td>{% ifchanged s.meeting %}{% if s.meeting.type.slug == 'ietf' %}IETF{% endif %}{{s.meeting.number}}{% endifchanged %}</td>
|
||||
<td>
|
||||
{% if s.status.slug == "sched" %}
|
||||
{% if s.meeting.type.slug == 'ietf' %}{{s.time|date:"D M d, Y Hi"}}{% else %}{{s.time|date:"D M d, Y"}}{% endif %}
|
||||
{% else %}
|
||||
{{s.status}}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{% if s.minutes %}<a href="{{ s.minutes.get_absolute_url }}">Minutes</a>{% endif %}</td>
|
||||
<td>{% if s.agenda %}<a href="{{ s.agenda.get_absolute_url }}">Agenda</a>{% endif %}</td>
|
||||
<td>{% if s.meeting.type.slug == 'ietf' %}<a href="{% url 'ietf.meeting.views.session_details' num=s.meeting.number acronym=s.group.acronym %}">Materials</a>{% endif %}</td>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
50
ietf/templates/group/meetings.html
Normal file
50
ietf/templates/group/meetings.html
Normal file
|
@ -0,0 +1,50 @@
|
|||
{% extends "group/group_base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
|
||||
{% block title %}Meetings{% if group %} for {{group.acronym}}{% endif %}{% endblock %}
|
||||
|
||||
{% block group_content %}
|
||||
{% origin %}
|
||||
{% if in_progress %}
|
||||
<div class="panel panel-default" id="inprogressmeets">
|
||||
<div class="panel-heading">
|
||||
Meetings in progress
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% with in_progress as sessions %}
|
||||
{% include "group/meetings-row.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if future %}
|
||||
<div class="panel panel-default" id="futuremeets">
|
||||
<div class="panel-heading">
|
||||
Future Meetings
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% with future as sessions %}
|
||||
{% include "group/meetings-row.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if past %}
|
||||
<div class="panel panel-default" id="pastmeets">
|
||||
<div class="panel-heading">
|
||||
Past Meetings
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% with past as sessions %}
|
||||
{% include "group/meetings-row.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div>This page shows meetings within the last four years. For earlier meetings, please see the proceedings.</div>
|
||||
|
||||
{% endblock %}
|
|
@ -6,20 +6,25 @@
|
|||
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
<h1>{{ meeting }} : {{ acronym }} : {{ time }} </h1>
|
||||
<h1>{{ meeting }} : {{ acronym }}</h1>
|
||||
|
||||
{% if session.name %}
|
||||
<h2>{{ session.name }}</h2>
|
||||
{% endif %}
|
||||
{% for session in sessions %}
|
||||
<h2>{{ session.time }}{% if session.name %} : {{ session.name }}{% endif %}</h2>
|
||||
|
||||
{% if filtered_sessionpresentation_set %}
|
||||
<p>Materials:</p>
|
||||
{% if session.filtered_sessionpresentation_set %}
|
||||
<p>Materials:</p>
|
||||
|
||||
<ul>
|
||||
{% for pres in filtered_sessionpresentation_set %}
|
||||
<li><a href="{% url 'doc_view' name=pres.document.name rev=pres.rev%}">{{ pres.document.name }}-{{ pres.rev }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
<table class="table table-condensed table-striped">
|
||||
{% for pres in session.filtered_sessionpresentation_set %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{% url 'doc_view' name=pres.document.name rev=pres.rev%}">{{pres.document.title}} ({{ pres.document.name }}-{{ pres.rev }})
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
|
||||
{% block title %}{{ meeting }} : {{ acronym }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
<h1>{{ meeting }} : {{ acronym }}</h1>
|
||||
|
||||
<ul>
|
||||
{% for session in sessions %}
|
||||
<li> <a href="{{ forloop.counter }}/">{{session}}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock %}
|
Loading…
Reference in a new issue