From 951670e9dfc67c55b0bf98d7da63b03fd7e2d5ec Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Tue, 29 Oct 2013 22:44:13 +0000 Subject: [PATCH] New view code and templates for agenda pages, updating all agenda templates to take schedule-specific information so that they will work with arbitrary schedules, not just the official schedule for a meeting. - Legacy-Id: 6537 --- ietf/meeting/urls.py | 10 +- ietf/meeting/views.py | 48 +++---- .../{agenda_utc.html => agenda-utc.html} | 132 ++++++++++-------- ietf/templates/meeting/agenda.csv | 30 +++- ietf/templates/meeting/agenda.html | 1 + ietf/templates/meeting/agenda.ics | 32 ++--- 6 files changed, 136 insertions(+), 117 deletions(-) rename ietf/templates/meeting/{agenda_utc.html => agenda-utc.html} (58%) diff --git a/ietf/meeting/urls.py b/ietf/meeting/urls.py index 5433a68f7..afc07960e 100644 --- a/ietf/meeting/urls.py +++ b/ietf/meeting/urls.py @@ -8,15 +8,15 @@ from ietf.meeting import ajax urlpatterns = patterns('', (r'^(?P\d+)/materials.html$', views.materials), (r'^agenda/$', views.agenda), - (r'^agenda-utc(?:.html)?$', views.html_agenda_utc), - (r'^agenda(?:.html)?$', views.agenda), + (r'^(?Pagenda-utc)(?P.html)?$', views.agenda), + (r'^agenda(?P.html)?$', views.agenda), (r'^agenda/edit$', views.edit_agenda), (r'^requests.html$', redirect_to, {"url": '/meeting/requests', "permanent": True}), (r'^requests$', views.meeting_requests), (r'^agenda(?P.txt)$', views.agenda), (r'^agenda/agenda.ics$', views.ical_agenda), (r'^agenda.ics$', views.ical_agenda), - (r'^agenda.csv$', views.csv_agenda), + (r'^agenda(?P.csv)$', views.agenda), (r'^agenda/week-view.html$', views.week_view), (r'^week-view.html$', views.week_view), (r'^(?P\d+)/schedule/edit$', views.edit_agenda), @@ -24,12 +24,12 @@ urlpatterns = patterns('', (r'^(?P\d+)/schedule/(?P[A-Za-z0-9-:_]+)/details$', views.edit_agenda_properties), (r'^(?P\d+)/schedule/(?P[A-Za-z0-9-:_]+)(?P.html)?/?$', views.agenda), (r'^(?P\d+)/agenda(?P.html)?/?$', views.agenda), - (r'^(?P\d+)/agenda-utc(?:.html)?/?$', views.html_agenda_utc), + (r'^(?P\d+)/(?Pagenda-utc)(?P.html)?/?$', views.agenda), (r'^(?P\d+)/requests.html$', redirect_to, {"url": '/meeting/%(num)s/requests', "permanent": True}), (r'^(?P\d+)/requests$', views.meeting_requests), (r'^(?P\d+)/agenda(?P.txt)$', views.agenda), (r'^(?P\d+)/agenda.ics$', views.ical_agenda), - (r'^(?P\d+)/agenda.csv$', views.csv_agenda), + (r'^(?P\d+)/agenda(?P.csv)$', views.agenda), (r'^(?P\d+)/agendas/edit$', views.edit_agendas), (r'^(?P\d+)/timeslots/edit$', views.edit_timeslots), (r'^(?P\d+)/rooms$', ajax.timeslot_roomsurl), diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index ee3b5dc08..ccac6e02d 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -432,14 +432,14 @@ def iphone_agenda(request, num, name): "wg_list" : wgs, "rg_list" : rgs, "area_list" : areas}, context_instance=RequestContext(request)) -def agenda(request, num=None, name=None, ext=".html"): - if ext is None: - ext = ".html" +def agenda(request, num=None, name=None, base=None, ext=None): + base = base if base else 'agenda' + ext = ext if ext else '.html' mimetype = {".html":"text/html", ".txt": "text/plain", ".ics":"text/calendar", ".csv":"text/csv"} meeting = get_meeting(num) schedule = get_schedule(meeting, name) updated = Switches().from_object(meeting).updated() - return HttpResponse(render_to_string("meeting/agenda"+ext, + return HttpResponse(render_to_string("meeting/"+base+ext, {"schedule":schedule, "updated": updated}, RequestContext(request)), mimetype=mimetype[ext]) def read_agenda_file(num, doc): @@ -633,13 +633,15 @@ def week_view(request, num=None): return render_to_response(template, {"timeslots":timeslots,"render_types":["Session","Other","Break","Plenary"]}, context_instance=RequestContext(request)) -def ical_agenda(request, num=None, name=None): +def ical_agenda(request, num=None, name=None, ext=None): meeting = get_meeting(num) + schedule = get_schedule(meeting, name) + updated = Switches().from_object(meeting).updated() q = request.META.get('QUERY_STRING','') or "" - filter = urllib.unquote(q).lower().split(','); - include = set(filter) - include_types = set(["Plenary","Other"]) + filter = set(urllib.unquote(q).lower().split(',')) + include = [ i for i in filter if not (i.startswith('-') or i.startswith('~')) ] + include_types = set(["plenary","other"]) exclude = [] # Process the special flags. @@ -651,38 +653,26 @@ def ical_agenda(request, num=None, name=None): # Non-Working Group "wg names" include: # edu, ietf, tools, iesg, iab - for item in include: + for item in filter: if item: if item[0] == '-' and item[1] == '~': - include_types -= set([item[2:3].upper()+item[3:]]) + include_types -= set([item[2:]]) elif item[0] == '-': exclude.append(item[1:]) elif item[0] == '~': - include_types |= set([item[1:2].upper()+item[2:]]) + include_types |= set([item[1:]]) - timeslots = TimeSlot.objects.filter(Q(meeting__id = meeting.id), - Q(type__name__in = include_types) | - Q(sessions__group__acronym__in = filter) | - Q(sessions__group__parent__acronym__in = filter) - ).exclude(Q(sessions__group__acronym__in = exclude)).distinct() + assignments = schedule.assignments.filter( + Q(timeslot__type__slug__in = include_types) | + Q(session__group__acronym__in = include) | + Q(session__group__parent__acronym__in = include) + ).exclude(session__group__acronym__in = exclude).distinct() #.exclude(Q(session__group__isnull = False), #Q(session__group__acronym__in = exclude) | #Q(session__group__parent__acronym__in = exclude)) - if meeting.time_zone: - try: - tzfn = os.path.join(settings.TZDATA_ICS_PATH, meeting.time_zone + ".ics") - tzf = open(tzfn) - icstext = tzf.read() - vtimezone = re.search("(?sm)(\nBEGIN:VTIMEZONE.*\nEND:VTIMEZONE\n)", icstext).group(1).strip() - tzf.close() - except IOError: - vtimezone = None - else: - vtimezone = None - return HttpResponse(render_to_string("meeting/agenda.ics", - {"timeslots":timeslots, "meeting":meeting, "vtimezone": vtimezone }, + {"schedule":schedule, "assignments":assignments, "updated":updated}, RequestContext(request)), mimetype="text/calendar") def csv_agenda(request, num=None, name=None): diff --git a/ietf/templates/meeting/agenda_utc.html b/ietf/templates/meeting/agenda-utc.html similarity index 58% rename from ietf/templates/meeting/agenda_utc.html rename to ietf/templates/meeting/agenda-utc.html index 87786295e..8cd8dcd07 100644 --- a/ietf/templates/meeting/agenda_utc.html +++ b/ietf/templates/meeting/agenda-utc.html @@ -2,7 +2,7 @@ {% load ietf_filters %} {# Copyright The IETF Trust 2007, All Rights Reserved #} {% load humanize %} -{% block title %}IETF {{ meeting.number }} Meeting Agenda{% endblock %} +{% block title %}IETF {{ schedule.meeting.number }} Meeting Agenda{% endblock %} {% block morecss %} table#agenda { border: 0; border-collapse:collapse; } @@ -22,7 +22,7 @@ table#wg-selector { border:1px solid black; border-collapse:collapse; } table#ics-preconfig { border:1px solid black; border-collapse:collapse; margin-top:24px; margin-bottom:24px;} #weekview.hidden { display: none; } -#weekview { border: none; margin: 0 0 0 0;} +#weekview { border: none; margin: 0 0 0 0; overflow: hidden;} #ical-link.hidden { display: none; } #ical-link { margin: 10px 0 0 0; padding: 10px; text-align: center; background-color: #2647a0; color: #FFFFFF } #ical-link A:link { color: #FFFFFF; } @@ -74,22 +74,14 @@ img.hidden { display: none; } {% endblock morecss %} -{% block pagehead %} +{% block js %} - - - + +{% endblock js %} -{% endblock pagehead %} {% block bodyAttrs %}onload='setGroupState();updateAgendaColors()'{% endblock %} {% block content %} -

IETF {{ meeting.number }} Meeting Agenda

- -

{{ meeting.city }}, {{ meeting.date|date:"F j" }} – {% ifnotequal meeting.date.month meeting.end_date.month %}{{ meeting.end_date|date:"F " }}{% endifnotequal %}{{ meeting.end_date|date:"j, Y" }}
-Updated {{ modified|date:"Y-m-d H:i:s T" }}

Time zone information:

The agenda times in this version of the agenda @@ -98,16 +90,19 @@ Updated {{ modified|date:"Y-m-d H:i:s T" }}

-
+

IETF {{ schedule.meeting.number }} Meeting Agenda

+ +

{{ schedule.meeting.city }}, {{ schedule.meeting.date|date:"F j" }} – {% ifnotequal schedule.meeting.date.month schedule.meeting.end_date.month %}{{ schedule.meeting.end_date|date:"F " }}{% endifnotequal %}{{ schedule.meeting.end_date|date:"j, Y" }}
+Updated {{ updated|date:"Y-m-d H:i:s T" }}

-(There's also a agenda with local times, a plaintext agenda and a tools-style agenda available)
+(There's also a agenda with local times, a plaintext agenda and a tools-style agenda available)

IETF agendas are subject to change, up to and during the meeting.

-{# cache this part for 15 minutes -- it takes 3-6 seconds to generate #} -{% load cache %}{% cache 900 ietf_meeting_agenda_utc meeting.number %} +{# cache this part for 5 minutes -- it takes 3-6 seconds to generate #} +{% load cache %}{% cache 3 ietf_meeting_agenda_utc schedule.meeting.number %} You can customize the agenda below to show only selected working group sessions. To be able to return to the customized view later, bookmark the resulting URL.
@@ -118,18 +113,18 @@ You can customize the agenda below to show only selected working group sessions. - {% for area in area_list %} + {% for area in schedule.area_list %} {% endfor %} - {% for wg in wg_list %}{% ifchanged wg.parent.acronym %}{% if forloop.counter > 1 %} + {% for wg in schedule.groups %}{% ifchanged wg.parent.acronym %}{% if forloop.counter > 1 %} {% endif %} - - + - +
Preconfigured .ics links: - {% for area in area_list %} - {{area|upper}} • + {% for area in schedule.area_list %} + {{area|upper}} • {% endfor %} - Non-Area Events + Non-Area Events
-{% if meeting.agenda_note %}

{{ meeting.agenda_note|safe }}

{% endif %} +{% if schedule.meeting.agenda_note %}

{{ schedule.meeting.agenda_note|safe }}

{% endif %} -{% for slot in timeslots %} +{% for item in schedule.assignments.all %} {% ifchanged %} {% endifchanged %} - {% ifchanged %} + {% if item.timeslot.type.slug == 'session' %} + {% ifchanged %} - {% endifchanged %} - {% if slot.type.name = 'Session' %} {% if slot.session.group %} - + {% endifchanged %} + {% endif %} + {% if item.timeslot.type.slug == 'break' or item.timeslot.type.slug == 'reg' or item.timeslot.type.slug == 'other' or item.timeslot.type.slug == 'plenary' %} + {% ifchanged %} + + + + + {% endifchanged %} + {% endif %} + {% if item.timeslot.type.slug = 'session' %} {% if item.session.group %} + - + + + {% if item.session.group.charter %}{{item.session.group.acronym}} + {% else %}{{item.session.group.acronym}}{% endif %} - + + {% if item.session.agenda %}{{item.session.group.name}} + {% else %}{{item.session.group.name}}{% endif %} + {% if item.session.group.state.name = "BOF" %} BOF {% endif %} + {% if item.session.agenda_note %} +
{{item.session.agenda_note}}{% endif %} + - + {% endif %} {% endif %} - {% if slot.type.name = 'Plenary' %} + {% if item.timeslot.type.slug = 'plenary' %}
-

{{ slot.time|date:"l"|upper }}, {{ slot.time|date:"F j, Y" }}

+

{{ item.timeslot.time|date:"l"|upper }}, {{ item.timeslot.time|date:"F j, Y" }}

- {{slot.utc_start_time|date:"M d"}}   - {{slot.utc_start_time|date:"Hi"}}-{{slot.utc_end_time|date:"Hi"}} UTC + {{ item.timeslot.utc_start_time|date:"M d"}}   + {{ item.timeslot.utc_start_time|date:"Hi"}}-{{item.timeslot.utc_end_time|date:"Hi"}} UTC - {% if slot.type.name == 'Session' %}{{ slot.time|date:"l"}}{% endif %} - {{slot.name}} - {% if slot.type.name != 'Session' %} - - {% if slot.show_location %}{{slot.get_location|escape}}{% endif %} - {% endif %} + {{ item.timeslot.time|date:"l"}} {{item.timeslot.name}}
+ {{ item.timeslot.utc_start_time|date:"M d"}}   + {{ item.timeslot.utc_start_time|date:"Hi"}}-{{item.timeslot.utc_end_time|date:"Hi"}} UTC + + {{item.timeslot.name}} + - + {% if item.timeslot.show_location %}{{item.timeslot.get_location|escape}}{% endif %} +
- {% if slot.show_location %}{{slot.get_location|escape}}{% endif %}{{slot.session.group.parent.acronym|upper}}{% if item.timeslot.show_location %}{{item.timeslot.get_location|escape}}{% endif %}{{item.session.group.parent.acronym|upper}} - {% if slot.session.group.charter %}{{slot.session.group.acronym}} - {% else %}{{slot.session.group.acronym}}{% endif %} - - {% if slot.session.agenda %}{{slot.session.group.name}} - {% else %}{{slot.session.group.name}}{% endif %} - {% if slot.session.group.state.name = "BOF" %} BOF {% endif %} - {% if slot.session.agenda_note %} -
{{slot.session.agenda_note}}{% endif %}
{% if slot.session.agenda %}drafts: tar|pdf{%endif%}{% if item.session.agenda %}drafts: tar|pdf{%endif%}
- {% if slot.session.agenda %} - {% if slot.session.agenda.file_extension in show_inline%} - + {% if item.session.agenda %} + {% if item.session.agenda.file_extension == "txt" or item.session.agenda.file_extension == "html" or item.session.agenda.file_extension == "htm" %} + {% else %} - Agenda submitted in {{slot.session.agenda.file_extension|upper}} format + Agenda submitted in {{item.session.agenda.file_extension|upper}} format {% endif %} {% else %} No Agenda Submitted {% endif %} - {% if slot.session.slides %} + {% if item.session.slides %}

Slides:

-
    {% for slide in slot.session.slides %} +
      {% for slide in item.session.slides %}
    1. {{ slide.title|clean_whitespace }} @@ -222,14 +230,14 @@ You can customize the agenda below to show only selected working group sessions.
- - {% if slot.session.slides %} + + {% if item.session.slides %}

Slides:

-
    {% for slide in slot.session.slides %} +
      {% for slide in item.session.slides %}
    1. {{ slide.title|clean_whitespace }} diff --git a/ietf/templates/meeting/agenda.csv b/ietf/templates/meeting/agenda.csv index 3e5770e7d..9485963af 100644 --- a/ietf/templates/meeting/agenda.csv +++ b/ietf/templates/meeting/agenda.csv @@ -1,5 +1,25 @@ -{% load humanize %}{% autoescape off %}{% load ietf_filters %}"Date","Start","End","Session","Room","Area","Acronym","Type","Description","Session ID","Agenda","Slides" -{% for slot in timeslots %}{% ifchanged %}{% if slot.reg_info %}"{{ slot.meeting_date|date:"Y-m-d" }}","{{ slot.registration.time_desc|slice:":4" }}","{{ slot.registration.time_desc|slice:"5:9" }}","Registration","{{ venue.reg_area_name }}","","","","{{ slot.registration.name }}","r{{slot.day_id}}","","" -{% endif %}{% endifchanged %}{% if slot.session_name %}{% if slot.break_info %}"{{ slot.meeting_date|date:"Y-m-d" }}","{{ slot.break_info.time_desc|slice:":4" }}","{{ slot.break_info.time_desc|slice:"5:9" }}","Break","{{ venue.break_area_name }}","","","","{{ slot.break_info.name }}","b{{slot.time_id}}","","" -{% endif %}{% endif %}{% for session in slot.sessions_by_area %}"{{ slot.meeting_date|date:"Y-m-d" }}","{{ slot.time_desc|slice:":4" }}","{{ slot.time_desc|slice:"5:9" }}","{{ slot.session_name }}","{{ session.info.room_id.room_name }}","{{ session.info.area|upper }}","{{ session.info.acronym }}","{{ session.info.group_type_str }}","{{ session.info.acronym_name }}","{{session.info.pk}}","{% if session.info.agenda_file %}http://datatracker.ietf.org/meeting/{{ meeting.num }}/agenda/{{ session.info.acronym }}/{% endif %}","{% if session.info.slides %}{% for slide in session.info.slides %}http://www.ietf.org/proceedings/{{ slide.file_loc }}{% if not forloop.last %}|{% endif %}{% endfor %}{% endif %}" -{% endfor %}{% endfor %}{% endautoescape %} +{% load humanize %}{% autoescape off %}{% load ietf_filters %}"Date","Start","End","Session","Room","Area","Acronym","Type","Description","Session ID","Agenda","Slides"{% for item in schedule.assignments.all.distinct %} + +{% if item.timeslot.type.slug == "break" %} + +"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","Break","{{ schedule.meeting.break_area}}","","","","{{ item.timeslot.name }}","b{{ item.timeslot.pk }}","","" + +{% endif %}{% if item.timeslot.type.slug == "reg" %} + +"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","{{ item.timeslot.type.name }}","{{ schedule.meeting.reg_area }}","","","","{{ item.timeslot.name }}","r{{item.timeslot.pk}}","","" + +{% endif %}{% if item.timeslot.type.slug == "other" %} + +"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","None","{{ item.timeslot.location.name }}","","{{ item.session.group.acronym }}","{% if item.session.group.parent %}{{item.session.group.parent.acronym|upper}}{% endif %}","{{ item.session.name }}","{{item.session.pk}}","","" + + +{% endif %}{% if item.timeslot.type.slug == "plenary" %} + +"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","{{ item.session.name }}","{{ item.timeslot.location.name }}","","{{ item.session.group.acronym }}","","{{ item.session.name }}","{{item.session.pk}}","{% if item.session.agenda %}http://datatracker.ietf.org/meeting/{{ schedule.meeting.number }}/agenda/{{ item.session.agenda.external_url }}{% endif %}","{% if item.session.slides %}{% for slide in item.session.slides %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/slides/{{ slide.external_url }}{% if not forloop.last %}|{% endif %}{% endfor %}{% endif %}" + +{% endif %}{% if item.timeslot.type.slug == "session" and item.session.group %} + +"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","{{ item.timeslot.name }}","{{ item.timeslot.location.name }}","{{ item.session.group.parent.acronym|upper }}","{{ item.session.group.acronym }}","{{ item.session.type }}","{{ item.session.group.name }}","{{ item.session.pk}}","{% if item.session.agenda %}http://datatracker.ietf.org/meeting/{{ schedule.meeting.number }}/agenda/{{ item.session.agenda.external_url }}{% endif %}","{% if item.session.slides %}{% for slide in item.session.slides %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/slides/{{ slide.external_url }}{% if not forloop.last %}|{% endif %}{% endfor %}{% endif %}" + + +{% endif %}{% endfor %}{% endautoescape %} diff --git a/ietf/templates/meeting/agenda.html b/ietf/templates/meeting/agenda.html index 0c388602f..49f876a8d 100644 --- a/ietf/templates/meeting/agenda.html +++ b/ietf/templates/meeting/agenda.html @@ -81,6 +81,7 @@ img.hidden { display: none; } {% endblock pagehead %} {% block bodyAttrs %}onload='setGroupState();updateAgendaColors()'{% endblock %} {% block content %} +

      IETF {{ schedule.meeting.number }} Meeting Agenda

      {{ schedule.meeting.city }}, {{ schedule.meeting.date|date:"F j" }} – {% ifnotequal schedule.meeting.date.month schedule.meeting.end_date.month %}{{ schedule.meeting.end_date|date:"F " }}{% endifnotequal %}{{ schedule.meeting.end_date|date:"j, Y" }}
      diff --git a/ietf/templates/meeting/agenda.ics b/ietf/templates/meeting/agenda.ics index 1e8ea14c2..59d1470a2 100644 --- a/ietf/templates/meeting/agenda.ics +++ b/ietf/templates/meeting/agenda.ics @@ -1,21 +1,21 @@ {% load humanize %}{% autoescape off %}{% load ietf_filters %}BEGIN:VCALENDAR VERSION:2.0 -METHOD:PUBLISH{% if vtimezone %} -{{vtimezone}}{% endif %}{% for slot in timeslots %} -BEGIN:VEVENT -UID:ietf-{{slot.meeting.number}}-{{slot.pk}} -SUMMARY:{% if slot.session.name %}{{slot.session.name}}{% else %}{% if slot.type.name == "Break" %}{{slot.name}}{% else %}{{slot.session.group.acronym|upper}} - {{slot.session.group.name}}{% endif%}{%endif%} -{% if slot.show_location %}LOCATION:{{slot.get_location}} -{% endif %}STATUS:TENTATIVE +METHOD:PUBLISH +PRODID:-//IETF//datatracker.ietf.org ical agenda//EN +{{schedule.meeting.vtimezone}}{% for item in assignments %}{% if item.session.group %}BEGIN:VEVENT +UID:ietf-{{schedule.meeting.number}}-{{item.timeslot.pk}} +SUMMARY:{% if item.session.name %}{{item.session.name|ics_esc}}{% else %}{% if not item.session.group %}{{item.timeslot.name|ics_esc}}{% else %}{{item.session.group.acronym|lower}} - {{item.session.group.name}}{% endif%}{%endif%} +{% if item.timeslot.show_location %}LOCATION:{{item.timeslot.get_location}} +{% endif %}STATUS:{{item.session.ical_status}} CLASS:PUBLIC -DTSTART{% if meeting.time_zone %};TZID="{{meeting.time_zone}}"{%endif%}:{{ slot.time|date:"Ymd" }}T{{slot.time|date:"Hi"}}00 -DTEND{% if meeting.time_zone %};TZID="{{meeting.time_zone}}"{%endif%}:{{ slot.end_time|date:"Ymd" }}T{{slot.end_time|date:"Hi"}}00 -DTSTAMP:{{ slot.modified|date:"Ymd" }}T{{ slot.modified|date:"His" }}Z -{% if slot.session.agenda %}URL:http://www.ietf.org{{slot.session.agenda.get_absolute_url}} -DESCRIPTION:{{slot.name}}\n{% if slot.session.agenda_note %} - Note: {{slot.session.agenda_note}}\n{% endif %}{% for material in slot.session.materials.all %} +DTSTART{% if schedule.meeting.time_zone %};TZID="{{schedule.meeting.time_zone}}"{%endif%}:{{ item.timeslot.time|date:"Ymd" }}T{{item.timeslot.time|date:"Hi"}}00 +DTEND{% if schedule.meeting.time_zone %};TZID="{{schedule.meeting.time_zone}}"{%endif%}:{{ item.timeslot.end_time|date:"Ymd" }}T{{item.timeslot.end_time|date:"Hi"}}00 +DTSTAMP:{{ item.timeslot.modified|date:"Ymd" }}T{{ item.timeslot.modified|date:"His" }}Z +{% if item.session.agenda %}URL:{{item.session.agenda.get_absolute_url}} +DESCRIPTION:{{item.timeslot.name|ics_esc}}\n{% if item.session.agenda_note %} + Note: {{item.session.agenda_note|ics_esc}}\n{% endif %}{% for material in item.session.materials.all %} \n{{material.type}}{% if material.type.name != "Agenda" %} - ({{material.title}}){% endif %}: + ({{material.title|ics_esc}}){% endif %}: http://www.ietf.org{{material.get_absolute_url}}\n{% endfor %} -{% endif %}END:VEVENT{% endfor %} -END:VCALENDAR{% endautoescape %} +{% endif %}END:VEVENT +{% endif %}{% endfor %}END:VCALENDAR{% endautoescape %}