Merge lp:~cjohnston/summit/add-hangout-display into lp:summit

Proposed by Chris Johnston
Status: Merged
Approved by: Michael Hall
Approved revision: 486
Merged at revision: 482
Proposed branch: lp:~cjohnston/summit/add-hangout-display
Merge into: lp:summit
Diff against target: 1864 lines (+893/-186)
8 files modified
summit/media/css/virt.css (+43/-0)
summit/schedule/forms.py (+71/-14)
summit/schedule/models/attendeemodel.py (+9/-2)
summit/schedule/models/summitmodel.py (+125/-37)
summit/schedule/templates/schedule/edit_hangout.html (+45/-0)
summit/schedule/templates/schedule/virtual_meeting.html (+146/-0)
summit/schedule/views.py (+400/-103)
summit/urls.py (+54/-30)
To merge this branch: bzr merge lp:~cjohnston/summit/add-hangout-display
Reviewer Review Type Date Requested Status
Michael Hall (community) Approve
Review via email: mp+149952@code.launchpad.net

Commit message

A bunch of pep8 fixes and a virt display

To post a comment you must log in.
486. By Chris Johnston

oops

Revision history for this message
Michael Hall (mhall119) wrote :

Looks great

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'summit/media/css/virt.css'
2--- summit/media/css/virt.css 1970-01-01 00:00:00 +0000
3+++ summit/media/css/virt.css 2013-02-22 02:06:23 +0000
4@@ -0,0 +1,43 @@
5+ div.wrapper {
6+ width: 98%;
7+ max-width: 98%;
8+ min-width: 98%;
9+ }
10+
11+ #top-nav, header {
12+ width: auto;
13+ }
14+
15+.span-3, .span-4, .span-6, .span-5, .span-7, .span-8, .span-9, .span-12 {
16+ clear: none;
17+ display: inline; /* HACK_IE_LTE_6: To fix IE 6 double margin bug. */
18+ float: left;
19+ margin: 0;
20+ padding: 0;
21+ position: relative;
22+}
23+.span-3 {
24+ width: 25%;
25+}
26+.span-4 {
27+ width: 39%; /* 300px / 15px */
28+}
29+.span-5 {
30+ width: 49%; /* 300px / 15px */
31+}
32+.span-6 {
33+ width: 50%; /* 460px / 15px */
34+}
35+.span-7 {
36+ width: 59%; /* 300px / 15px */
37+}
38+.span-8 {
39+ width: 77%; /* 620px / 15px */
40+ }
41+.span-9 {
42+ width: 74%; /* 700px / 15px */
43+}
44+.span-12 { /** Full width. */
45+ width: 100%; /* 940px / 15px */
46+ margin-right: 0;
47+}
48
49=== modified file 'summit/schedule/forms.py'
50--- summit/schedule/forms.py 2012-08-12 22:32:46 +0000
51+++ summit/schedule/forms.py 2013-02-22 02:06:23 +0000
52@@ -22,6 +22,7 @@
53
54 from common.forms import RenderableMixin
55
56+
57 class MultipleAttendeeField(forms.ModelMultipleChoiceField):
58 def label_from_instance(self, obj):
59 return u"%s %s (%s)" % (
60@@ -36,12 +37,8 @@
61 required=False)
62
63 class Media:
64- css = {'all': (
65- '/media/css/colortip-1.0-jquery.css',
66- )}
67- js = (
68- '/media/js/colortip-1.0-jquery.js',
69- )
70+ css = {'all': ('/media/css/colortip-1.0-jquery.css',)}
71+ js = ('/media/js/colortip-1.0-jquery.js',)
72
73 def __init__(self, *args, **kwargs):
74 if 'instance' in kwargs:
75@@ -72,6 +69,7 @@
76 old_save_m2m = self.save_m2m
77 else:
78 old_save_m2m = None
79+
80 def save_m2m():
81 if old_save_m2m is not None:
82 old_save_m2m()
83@@ -94,43 +92,102 @@
84 class CreateMeeting(MeetingFormBase, RenderableMixin):
85 class Meta:
86 model = Meeting
87- fields = ('title', 'description', 'tracks', 'type', 'private', 'spec_url', 'wiki_url',
88- 'pad_url', 'requires_dial_in', 'slots', 'approved', 'video', 'override_break')
89+ fields = (
90+ 'title',
91+ 'description',
92+ 'tracks',
93+ 'type',
94+ 'private',
95+ 'spec_url',
96+ 'wiki_url',
97+ 'pad_url',
98+ 'requires_dial_in',
99+ 'slots',
100+ 'approved',
101+ 'video',
102+ 'override_break'
103+ )
104+
105
106 class OrganizerEditMeeting(MeetingFormBase, RenderableMixin):
107 class Meta:
108 model = Meeting
109- fields = ('title', 'description', 'tracks', 'type', 'private', 'spec_url', 'wiki_url',
110- 'pad_url', 'requires_dial_in', 'slots', 'approved', 'video', 'override_break')
111+ fields = (
112+ 'title',
113+ 'description',
114+ 'tracks',
115+ 'type',
116+ 'private',
117+ 'spec_url',
118+ 'wiki_url',
119+ 'pad_url',
120+ 'requires_dial_in',
121+ 'slots',
122+ 'approved',
123+ 'video',
124+ 'override_break'
125+ )
126+
127
128 class ProposeMeeting(MeetingFormBase, RenderableMixin):
129 class Meta:
130 model = Meeting
131- fields = ('title', 'description', 'tracks', 'spec_url', 'wiki_url', 'pad_url')
132+ fields = (
133+ 'title',
134+ 'description',
135+ 'tracks',
136+ 'spec_url',
137+ 'wiki_url',
138+ 'pad_url'
139+ )
140
141
142 class EditMeeting(MeetingFormBase, RenderableMixin):
143 class Meta:
144 model = Meeting
145- fields = ('title', 'description', 'tracks', 'spec_url', 'wiki_url', 'pad_url')
146+ fields = (
147+ 'title',
148+ 'description',
149+ 'tracks',
150+ 'spec_url',
151+ 'wiki_url',
152+ 'pad_url'
153+ )
154+
155
156 class MeetingReview(forms.ModelForm, RenderableMixin):
157 class Meta:
158 model = Meeting
159 fields = ('approved',)
160
161+
162 class AttendMeeting(forms.ModelForm, RenderableMixin):
163 class Meta:
164 model = Participant
165 fields = ('participation',)
166+
167 def __init__(self, *args, **kwargs):
168 super(AttendMeeting, self).__init__(*args, **kwargs)
169- self.fields['participation'].choices = ((u'ATTENDING', u'Attending'), (u'INTERESTED', u'Very interested in attending'))
170+ self.fields['participation'].choices = (
171+ (u'ATTENDING', u'Attending'),
172+ (u'INTERESTED', u'Very interested in attending')
173+ )
174+
175
176 class OrganizerChangeAttend(forms.ModelForm, RenderableMixin):
177 class Meta:
178 model = Participant
179 fields = ('participation',)
180+
181 def __init__(self, *args, **kwargs):
182 super(OrganizerChangeAttend, self).__init__(*args, **kwargs)
183- self.fields['participation'].choices = ((u'INTERESTED', u'Should Attend'), (u'REQUIRED', u'Required to Attend'))
184+ self.fields['participation'].choices = (
185+ (u'INTERESTED', u'Should Attend'),
186+ (u'REQUIRED', u'Required to Attend')
187+ )
188+
189+
190+class EditMeetingHangout(forms.ModelForm, RenderableMixin):
191+ class Meta:
192+ model = Meeting
193+ fields = ('hangout_url', 'broadcast_url')
194
195=== modified file 'summit/schedule/models/attendeemodel.py'
196--- summit/schedule/models/attendeemodel.py 2012-04-30 16:48:43 +0000
197+++ summit/schedule/models/attendeemodel.py 2013-02-22 02:06:23 +0000
198@@ -45,7 +45,7 @@
199 verbose_name='Willing to be Crew',
200 default=False)
201 secret_key_id = models.CharField(max_length=32, blank=True, null=True)
202-
203+
204 class Meta:
205 app_label = 'schedule'
206 ordering = ('user__username', 'summit')
207@@ -86,7 +86,14 @@
208 secret_key = property(get_secret_key, set_secret_key)
209
210 def ical_url(self):
211- return getattr(settings, 'SITE_ROOT', 'http://summit.ubuntu.com') + reverse('summit.schedule.views.user_private_ical', args=(self.summit.name,self.secret_key))
212+ return getattr(
213+ settings,
214+ 'SITE_ROOT',
215+ 'http://summit.ubuntu.com'
216+ ) + reverse(
217+ 'summit.schedule.views.user_private_ical',
218+ args=(self.summit.name, self.secret_key)
219+ )
220
221 def update_from_launchpad(self, elem):
222 """Update from Launchpad data."""
223
224=== modified file 'summit/schedule/models/summitmodel.py'
225--- summit/schedule/models/summitmodel.py 2013-02-20 17:33:14 +0000
226+++ summit/schedule/models/summitmodel.py 2013-02-22 02:06:23 +0000
227@@ -47,6 +47,8 @@
228
229 #Monkey patch for better use in the admin
230 User._meta.ordering = ['username']
231+
232+
233 def unicode_user(user):
234 display = []
235 if user.first_name:
236@@ -56,9 +58,10 @@
237 if len(display) == 0:
238 return user.username
239 else:
240- return user.username + ' (' +' '.join(display) + ')'
241+ return user.username + ' (' + ' '.join(display) + ')'
242 User.__unicode__ = unicode_user
243
244+
245 class SummitManager(CurrentSiteManager):
246
247 def next(self):
248@@ -68,6 +71,7 @@
249 # No summits have been defined in the database yet
250 return Summit(name="no_summits", title="No Summits Defined")
251
252+
253 class Summit(models.Model):
254 STATE_CHOICES = (
255 (u'sponsor', u'Sponsorship Requests'),
256@@ -81,22 +85,51 @@
257 sites = models.ManyToManyField(Site)
258 location = models.CharField(max_length=100, blank=True)
259 description = models.TextField(max_length=2047, blank=True)
260- etherpad = models.URLField(verify_exists=False, max_length=75, blank=False, default='http://pad.ubuntu.com/', help_text="Enter the URL of the etherpad server you would like to use")
261- qr = models.URLField(verify_exists=False, max_length=100, blank=True, default='', help_text="Enter the URL of the QR code for mobile device application")
262+ etherpad = models.URLField(
263+ verify_exists=False,
264+ max_length=75,
265+ blank=False,
266+ default='http://pad.ubuntu.com/',
267+ help_text="Enter the URL of the etherpad server you would like to use"
268+ )
269+ qr = models.URLField(
270+ verify_exists=False,
271+ max_length=100,
272+ blank=True,
273+ default='',
274+ help_text="Enter the URL of the QR code for mobile device application"
275+ )
276 hashtag = models.CharField(max_length=25, blank=True)
277- timezone = models.CharField(max_length=50,
278- choices=[(x, x) for x in pytz.common_timezones])
279+ timezone = models.CharField(
280+ max_length=50,
281+ choices=[(x, x) for x in pytz.common_timezones]
282+ )
283 last_update = models.DateTimeField(null=True, blank=True)
284- state = models.CharField(max_length=10, choices=STATE_CHOICES,
285- default=STATE_CHOICES[0][0])
286+ state = models.CharField(
287+ max_length=10,
288+ choices=STATE_CHOICES,
289+ default=STATE_CHOICES[0][0]
290+ )
291 date_start = models.DateField(blank=False, null=True)
292 date_end = models.DateField(blank=False, null=True)
293- managers = models.ManyToManyField(User, blank=True, related_name='managers')
294- schedulers = models.ManyToManyField(User, blank=True, related_name='schedulers')
295+ managers = models.ManyToManyField(
296+ User,
297+ blank=True,
298+ related_name='managers'
299+ )
300+ schedulers = models.ManyToManyField(
301+ User,
302+ blank=True,
303+ related_name='schedulers'
304+ )
305 virtual_summit = models.BooleanField(
306 help_text="Check this if the entire sprint is virtual"
307 )
308- help_text = models.TextField(null=True, blank=True, help_text='Summit specific instructions and links for getting help during the event')
309+ help_text = models.TextField(
310+ null=True,
311+ blank=True,
312+ help_text='Instructions and links for getting help during the event'
313+ )
314
315 objects = models.Manager()
316 on_site = SummitManager()
317@@ -109,7 +142,14 @@
318 return self.name
319
320 def get_absolute_url(self):
321- return getattr(settings, 'SITE_ROOT', 'http://summit.ubuntu.com') + reverse('summit.schedule.views.summit', args=(self.name,))
322+ return getattr(
323+ settings,
324+ 'SITE_ROOT',
325+ 'http://summit.ubuntu.com'
326+ ) + reverse(
327+ 'summit.schedule.views.summit',
328+ args=(self.name,)
329+ )
330
331 def localize(self, datetime):
332 """Convert a datetime to the summit-local timezone.
333@@ -172,7 +212,14 @@
334 return sorted(dates)
335
336 def ical_url(self):
337- return getattr(settings, 'SITE_ROOT', 'http://summit.ubuntu.com') + reverse('summit.schedule.views.ical', args=(self.name,))
338+ return getattr(
339+ settings,
340+ 'SITE_ROOT',
341+ 'http://summit.ubuntu.com'
342+ ) + reverse(
343+ 'summit.schedule.views.ical',
344+ args=(self.name,)
345+ )
346
347 def public_rooms(self):
348 """List of public rooms for this summit.
349@@ -192,7 +239,9 @@
350 else:
351 return cmp(a.track.title, b.track.title)
352
353- rooms = self.room_set.exclude(Q(type__exact='closed') | Q(type__exact='private'))
354+ rooms = self.room_set.exclude(
355+ Q(type__exact='closed') | Q(type__exact='private')
356+ )
357 return sorted(rooms, cmp=by_title)
358
359 def open_rooms(self):
360@@ -231,8 +280,12 @@
361 if sprints.count() > 0:
362 urls = [sprint.import_url for sprint in sprints]
363 else:
364- urls = [("https://launchpad.net/sprints/%s/+temp-meeting-export"
365- % self.name)]
366+ urls = [
367+ (
368+ "https://launchpad.net/sprints/%s/+temp-meeting-export"
369+ % self.name
370+ )
371+ ]
372 return urls
373
374 def update_from_launchpad_response(self, response, options={}):
375@@ -253,9 +306,16 @@
376 while trycounter <= retrytotal:
377 req = urllib2.Request(url)
378 req.add_header("Cache-Control", "no-cache")
379- req.add_header("Cookie", "lp=%s" % getattr(settings, "LP_AUTH_COOKIE", "please-don't-cache-me"))
380+ req.add_header(
381+ "Cookie",
382+ "lp=%s" % getattr(
383+ settings,
384+ "LP_AUTH_COOKIE",
385+ "please-don't-cache-me"
386+ )
387+ )
388 try:
389- export = urllib2.urlopen(req)
390+ export = urllib2.urlopen(req)
391 except urllib2.HTTPError, e:
392 trycounter += 1
393 if trycounter >= retrytotal:
394@@ -278,12 +338,16 @@
395 in_lp |= self.update_from_launchpad_response(sprint_info, options)
396
397 if not options.get('skip_meetings', False):
398- in_db = set(m for m in self.meeting_set.exclude(launchpad_blueprint_id__isnull=True))
399+ in_db = set(
400+ m for m in self.meeting_set.exclude(
401+ launchpad_blueprint_id__isnull=True
402+ )
403+ )
404
405 for extra in in_db.difference(in_lp):
406 print "Marking %s as removed" % extra.name
407 extra.agenda_set.all().delete()
408- extra.approved='REMOVED'
409+ extra.approved = 'REMOVED'
410 extra.save()
411
412 self.last_update = datetime.utcnow()
413@@ -298,19 +362,26 @@
414
415 print "user %s" % username
416 try:
417- attendee = self.attendee_set.get(user__username__exact=username[:30])
418+ attendee = self.attendee_set.get(
419+ user__username__exact=username[:30]
420+ )
421 except ObjectDoesNotExist:
422 try:
423 user = User.objects.get(username__exact=username[:30])
424 except ObjectDoesNotExist:
425- user = User.objects.create_user(username[:30], '', password=None)
426+ user = User.objects.create_user(
427+ username[:30],
428+ '',
429+ password=None
430+ )
431 launchpad.set_user_openid(user)
432
433 # Create with any start/end time since we overwrite shortly
434- attendee = self.attendee_set.create(user=user,
435- start=datetime.utcnow(),
436- end=datetime.utcnow())
437-
438+ attendee = self.attendee_set.create(
439+ user=user,
440+ start=datetime.utcnow(),
441+ end=datetime.utcnow()
442+ )
443
444 attendee.update_from_launchpad(elem)
445
446@@ -333,7 +404,12 @@
447 try:
448 meeting = self.meeting_set.get(launchpad_blueprint_id=bp_id)
449 except ObjectDoesNotExist:
450- meeting = self.meeting_set.create(name=name, title=full_name[:100], slots=slot_length, launchpad_blueprint_id=bp_id)
451+ meeting = self.meeting_set.create(
452+ name=name,
453+ title=full_name[:100],
454+ slots=slot_length,
455+ launchpad_blueprint_id=bp_id
456+ )
457 except:
458 pass
459
460@@ -347,13 +423,18 @@
461 This is a pretty simple best-fit/first-come-first-served scheduler,
462 but it suffices.
463 """
464- for meeting in self.meeting_set.filter(approved='APPROVED', agenda__isnull=True).order_by('id'):
465- meeting.try_schedule(with_interested = True)
466+ for meeting in self.meeting_set.filter(
467+ approved='APPROVED',
468+ agenda__isnull=True
469+ ).order_by('id'):
470+ meeting.try_schedule(with_interested=True)
471
472- for meeting in self.meeting_set.filter(approved='APPROVED', agenda__isnull=True).order_by('id'):
473+ for meeting in self.meeting_set.filter(
474+ approved='APPROVED',
475+ agenda__isnull=True
476+ ).order_by('id'):
477 meeting.try_schedule()
478
479-
480 def check_schedule(self):
481 """Check the schedule for existant errors."""
482 for meeting in self.meeting_set.all():
483@@ -361,14 +442,20 @@
484 try:
485 missing = meeting.check_schedule(agenda.slot, agenda.room)
486 if len(missing):
487- print "Warning: required people not available: %s at %s in %s: %s" % (
488- meeting, agenda.slot, agenda.room,
489- ', '.join(m.user.username for m in missing))
490+ print "Warning: required people not available:"
491+ "%s at %s in %s: %s" % (
492+ meeting,
493+ agenda.slot,
494+ agenda.room,
495+ ', '.join(m.user.username for m in missing)
496+ )
497 except meeting.SchedulingError, e:
498- print "Error: %s at %s in %s: %s" % (meeting,
499- agenda.slot,
500- agenda.room,
501- e)
502+ print "Error: %s at %s in %s: %s" % (
503+ meeting,
504+ agenda.slot,
505+ agenda.room,
506+ e
507+ )
508
509 def reschedule(self):
510 """Delete any automatically created agenda items that have problems."""
511@@ -426,6 +513,7 @@
512 return self.lead_set.filter(lead=attendee).exists()
513 return False
514
515+
516 class SummitSprint(models.Model):
517
518 summit = models.ForeignKey(Summit, related_name='sprint_set')
519
520=== added file 'summit/schedule/templates/schedule/edit_hangout.html'
521--- summit/schedule/templates/schedule/edit_hangout.html 1970-01-01 00:00:00 +0000
522+++ summit/schedule/templates/schedule/edit_hangout.html 2013-02-22 02:06:23 +0000
523@@ -0,0 +1,45 @@
524+{% extends "base.html" %}
525+
526+{% block page_name %}Edit Hangout - {{ summit.title }}{%endblock %}
527+{% block sub_nav %}{% endblock %}
528+
529+{% block extrahead %}{{ block.super }}
530+ <script type="text/javascript" src="{{MEDIA_URL}}js/colortip-1.0-jquery.js"></script>
531+ <link rel="stylesheet" type="text/css" href="{{MEDIA_URL}}css/colortip-1.0-jquery.css"/>
532+{% endblock %}
533+
534+{% block closure %}
535+<script type="text/javascript"><!--
536+$(document).ready(function(){
537+ $('span[rel*=help]').colorTip({color:'orange'});
538+});
539+--></script>
540+<style>
541+form ul {
542+ height: 12em;
543+ overflow-y: scroll;
544+ overflow-x: hidden;
545+}
546+</style>
547+{% endblock %}
548+
549+
550+{% block content %}
551+<div class="row">
552+ <article id="form" class="span-8">
553+ {% if form.errors %}
554+ <p style="color: red;">
555+ Please correct the error{{ form.errors|pluralize }} below.
556+ </p>
557+ {% endif %}
558+
559+ <form action="{{ request.path_info }}" method="POST">
560+ <fieldset>
561+ <h3>Edit Hangout</h3>
562+ {{ form.as_template }}
563+ {% if is_popup %}<input type="hidden" name="_popup" value="1">{% endif %}
564+ <input type="submit" name="submit" value="Save" class="submit-button" />
565+ </fieldset>
566+ </form>
567+ </article>
568+{% endblock %}
569
570=== added file 'summit/schedule/templates/schedule/virtual_meeting.html'
571--- summit/schedule/templates/schedule/virtual_meeting.html 1970-01-01 00:00:00 +0000
572+++ summit/schedule/templates/schedule/virtual_meeting.html 2013-02-22 02:06:23 +0000
573@@ -0,0 +1,146 @@
574+{% extends "base.html" %}
575+{% load schedule_perms datetime markup %}
576+
577+{% block page_name %}
578+ {{ meeting.title }} -
579+ {% if schedule.date %}{{ schedule.date|strftime:"%Y-%m-%d" }}{% endif %}
580+ {% if schedule.room %}{{ schedule.room.title }} - {{ summit.title }}{% endif %}
581+{% endblock %}
582+
583+{% block extrahead %}{{ block.super }}
584+ <link rel="stylesheet" type="text/css" media="screen" href="/media/css/virt.css" />
585+<meta property="fb:app_id" content="310260202349342" />
586+<meta property="og:title" content="{{ meeting.title }}{% if schedule.date %} - {{ schedule.date|strftime:"%Y-%m-%d" }}{% endif %}{% if schedule.room %}{{ schedule.room.title }}{% endif %}" />
587+{% if meeting.description %}
588+<meta property="og:description" content="{{ meeting.description|linebreaks|striptags }}" />
589+{% endif %}
590+<meta property="og:url" content="http://summit.ubuntu.com{% url summit.schedule.views.meeting meeting.summit.name, meeting.id, meeting.name|default:'-' %}" />
591+<meta property="og:image" content="http://summit.ubuntu.com/media/images/cof_orange_hex1.png" />
592+<meta property="og:site_name" content="The Summit Scheduler" />
593+<meta property="og:type" content="article" />
594+<meta itemprop="name" content="{{ meeting.title }}{% if schedule.date %} - {{ schedule.date|strftime:"%Y-%m-%d" }}{% endif %}{% if schedule.room %}{{ schedule.room.title }}{% endif %}" />
595+<meta itemprop="description" content="{{ meeting.description|linebreaks|striptags }}" />
596+{% endblock %}
597+
598+{% block sub_nav_links %}
599+ {% if meeting.private %}
600+ {% if meeting.private_key and meeting.private_key != '' %}
601+ <li><a class="sub-nav-item" href="{% url summit.schedule.views.private_meeting meeting.summit.name, meeting.private_key, meeting.name|default:'-' %}">Shared URL</a></li>
602+ {% else %}
603+ <li><a class="sub-nav-item" href="{% url summit.schedule.views.meeting meeting.summit.name, meeting.id, meeting.name|default:'-' %}+share">Share meeting</a></li>
604+ {% endif %}
605+ {% endif %}
606+
607+ {% if meeting.spec_url %}
608+ {% if summit_organizer or drafter %}
609+ <li><a class="sub-nav-item" href="{% url summit.schedule.views.attendee_review summit.name, meeting.id, meeting.name|default:'-' %}">Review attendees</a></li>
610+ <li><a class="sub-nav-item" href="{% url summit.schedule.views.edit_meeting_hangout summit.name, meeting.id, meeting.name|default:'-' %}">Edit Hangout Details</a></li>
611+ {% endif %}
612+ <li><a class="sub-nav-item" href="{{ meeting.spec_url }}">Blueprint</a></li>
613+ {% else %}
614+ {% if summit_organizer or drafter %}
615+ {% if not drafter %}
616+ <li><a class="sub-nav-item" href="{% url summit.schedule.views.organizer_edit_meeting summit.name, meeting.id, meeting.name|default:'-' %}">Edit meeting</a></li>
617+ {% endif %}
618+ {% if not summit_organizer %}
619+ <li><a class="sub-nav-item" href="{% url summit.schedule.views.edit_meeting summit.name, meeting.id, meeting.name|default:'-' %}">Edit meeting</a></li>
620+ {% endif %}
621+ <li><a class="sub-nav-item" href="{% url summit.schedule.views.attendee_review summit.name, meeting.id, meeting.name|default:'-' %}">Review attendees</a></li>
622+ <li><a class="sub-nav-item" href="{% url summit.schedule.views.edit_meeting_hangout summit.name, meeting.id, meeting.name|default:'-' %}">Edit Hangout Details</a></li>
623+ {% endif %}
624+ {% endif %}
625+
626+ {% if user_is_attending %}
627+ {% if user_is_participating %}
628+ <li><a class="sub-nav-item" href="{% url summit.schedule.views.unregister meeting.summit.name, meeting.id, meeting.name|default:'-' %}">Skip this meeting</a></li>
629+ {% endif %}
630+ {% else %}
631+ {% if meeting.spec_url %}
632+ <li><a class="sub-nav-item" href="{{ meeting.spec_url }}/+subscribe">Subscribe to blueprint</a></li>
633+ {% endif %}
634+ <li><a class="sub-nav-item" href="{% url summit.schedule.views.attend_meeting meeting.summit.name, meeting.id %}">Attend this meeting</a></li>
635+ {% endif %}
636+
637+ {% if scheduler %}
638+ <li><a class="sub-nav-item" href="{% url summit.schedule.views.meeting_copy meeting.summit.name, meeting.id, meeting.name|default:'-' %}">Copy meeting</a></li>
639+ {% endif %}
640+{% endblock %}
641+
642+{% block content %}
643+<div class="row">
644+<section class="span-9">
645+ <h2>{{ meeting.title }}</h2>
646+ <div id="description">
647+ {{ meeting.description|markdown:'safe' }}
648+ <h3><a href="{{ meeting.hangout_url }}">Join the Hangout on Air</a></h3>
649+ </div>
650+
651+</section>
652+<article class="span-3 last">
653+{% if meeting.private %}
654+{% else %}
655+<div class="share">
656+ <a href="http://www.reddit.com/submit" onclick="window.location = 'http://www.reddit.com/submit?url=' + encodeURIComponent(window.location); return false"> <img style="padding-bottom: 4px;"src="http://www.reddit.com/static/spreddit7.gif" alt="submit to reddit" border="0" /></a><br />
657+ <div id="fb-root"></div>
658+ <script>(function(d, s, id) {
659+ var js, fjs = d.getElementsByTagName(s)[0];
660+ if (d.getElementById(id)) {return;}
661+ js = d.createElement(s); js.id = id;
662+ js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=310260202349342";
663+ fjs.parentNode.insertBefore(js, fjs);
664+ }(document, 'script', 'facebook-jssdk'));</script>
665+ <div class="fb-like" data-href="" data-send="false" data-layout="box_count" data-width="40" data-show-faces="false" data-font="arial"></div>
666+ <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
667+ <g:plusone size="tall"></g:plusone>
668+ <a href="http://twitter.com/share" class="twitter-share-button" data-count="vertical" data-lang="en">Tweet</a>
669+ <script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
670+ <script src="http://www.stumbleupon.com/hostedbadge.php?s=5"></script>
671+</div>
672+
673+{% endif %}
674+</article>
675+</div>
676+<div class="row">
677+ <div class="span-4">
678+ <div align="center"><iframe width="420" height="295" src="{{ meeting.broadcast_url }}" frameborder="0" allowfullscreen></iframe></div>
679+ <iframe src="http://webchat.freenode.net?channels={% for ai in agenda_items %}{{ ai.room.irc_channel }}{% endfor %}&uio=Mj10cnVlJjQ9dHJ1ZSY5PXRydWUmMTA9dHJ1ZSYxMz1mYWxzZSYxND1mYWxzZQbf" width="100%" height="395"></iframe>
680+</div>
681+<div class="span-7 last">
682+ {% if meeting.private %}
683+ <h3>WARNING: Contents of this pad may not be private, and may be searcheable by non-attendees!</h3>
684+ {% endif %}
685+
686+<iframe width=100% height=700 src="{{ meeting.link_to_pad }}"></iframe>
687+</div>
688+</div>
689+<div class="row">
690+ {% ifnotequal meeting.type 'plenary' %}
691+ <div id="Attendees" class="span-4">
692+ <h3>Attendees</h3>
693+ {% for attendee in attendees %}
694+ <a href="http://launchpad.net/~{{ attendee.user.username }}">{% if attendee.participation = 'REQUIRED' %}<strong>{% endif %}{{ attendee.name }}{% if attendee.required %}</strong>{% endif %}</a>{% if not forloop.last %}, {% endif %}
695+ {% endfor %}
696+ </div>
697+ {% endifnotequal %}
698+ <div class="span-3">
699+{% if summit_organizer %}
700+ {% include "schedule/admin.html" %}
701+{% endif %}
702+ </div>
703+ <div id="Links" class="span-3 last">
704+ <h3>Links</h3>
705+ <ul>
706+ <li><a href="{{meeting.link_to_pad}}" target="_new">Notes in a separate window</a></li>
707+ <li><a href="{{meeting.edit_link_to_pad}}" target="_new">Edit notes window</a></li>
708+ {% if meeting.spec_url %}<li><a href="{{ meeting.spec_url }}">Blueprint</a></li>{% endif %}
709+ {% if meeting.wiki_url %}<li><a href="{{ meeting.wiki_url }}">Wiki page</a></li>{% endif %}
710+ {% for ai in agenda_items %}
711+ {% if ai.room.irc_channel %}<li><a href="https://webchat.freenode.net/?channels={{ai.room.irc_channel}}">IRC Channel: #{{ai.room.irc_channel}}</a></li>{% endif %}
712+ {% endfor %}
713+
714+ </ul>
715+ </div>
716+
717+</article>
718+</div>
719+{% endblock %}
720
721=== modified file 'summit/schedule/views.py'
722--- summit/schedule/views.py 2012-10-26 10:23:28 +0000
723+++ summit/schedule/views.py 2013-02-22 02:06:23 +0000
724@@ -49,7 +49,8 @@
725 EditMeeting,
726 MeetingReview,
727 AttendMeeting,
728- OrganizerChangeAttend
729+ OrganizerChangeAttend,
730+ EditMeetingHangout
731 )
732
733 __all__ = (
734@@ -60,6 +61,7 @@
735 'today_view',
736 )
737
738+
739 @summit_required
740 def summit(request, summit, attendee):
741 edit = False
742@@ -81,14 +83,17 @@
743 return render_to_response("schedule/summit.html", context,
744 context_instance=RequestContext(request))
745
746+
747 @summit_only_required
748 def search(request, summit):
749 query = request.GET.get('q', None)
750 if query:
751- meetings = summit.meeting_set.filter(Q(name__icontains=query) | Q(title__icontains=query))
752+ meetings = summit.meeting_set.filter(
753+ Q(name__icontains=query) | Q(title__icontains=query)
754+ )
755 else:
756 meetings = []
757-
758+
759 context = {
760 'summit': summit,
761 'query': query,
762@@ -96,17 +101,28 @@
763 }
764 return render_to_response("schedule/search.html", context,
765 context_instance=RequestContext(request))
766+
767+
768 @summit_required
769 def daily_schedule(request, summit, attendee, date):
770- viewdate = summit.as_localtime(datetime.datetime.strptime(date, "%Y-%m-%d"))
771+ viewdate = summit.as_localtime(
772+ datetime.datetime.strptime(date, "%Y-%m-%d")
773+ )
774 utc_date = summit.delocalize(viewdate)
775 day = datetime.timedelta(days=1)
776
777 schedule = SortedDict()
778 multislot_meetings = SortedDict()
779
780- for slot in summit.slot_set.filter(start_utc__gte=utc_date, end_utc__lte=(utc_date+day)).order_by('start_utc'):
781- if not (slot.type == 'open' or slot.type == 'plenary' or slot.type == 'lunch'):
782+ for slot in summit.slot_set.filter(
783+ start_utc__gte=utc_date,
784+ end_utc__lte=(utc_date+day)
785+ ).order_by('start_utc'):
786+ if not (
787+ slot.type == 'open' or
788+ slot.type == 'plenary' or
789+ slot.type == 'lunch'
790+ ):
791 continue
792 if not slot in schedule:
793 schedule[slot] = SortedDict()
794@@ -117,7 +133,7 @@
795 if count == 1:
796 del multislot_meetings[agenda]
797 else:
798- multislot_meetings[agenda] = count -1
799+ multislot_meetings[agenda] = count - 1
800
801 # Add meetings from this slot
802 for agenda in slot.agenda_set.select_related().order_by('room__name'):
803@@ -125,7 +141,7 @@
804 schedule[slot][agenda.room] = agenda
805 if agenda.meeting.slots > 1:
806 multislot_meetings[agenda] = agenda.meeting.slots - 1
807-
808+
809 if '_popup' in request.GET:
810 is_popup = True
811
812@@ -141,29 +157,49 @@
813 }
814 return render_to_response("schedule/daily.html", context,
815 context_instance=RequestContext(request))
816-
817+
818+
819 @summit_attendee_required
820 def attendee_schedule(request, summit, attendee):
821 pass
822-
823+
824+
825 @summit_required
826 def by_date(request, summit, attendee, date):
827 return _process_date_view(request, summit, attendee, date)
828
829+
830 @summit_required
831 def today_view(request, summit, attendee):
832 today = summit.localize(datetime.datetime.now()).date()
833- return _process_date_view(request, summit, attendee, today.strftime("%Y-%m-%d"))
834+ return _process_date_view(
835+ request,
836+ summit,
837+ attendee,
838+ today.strftime("%Y-%m-%d")
839+ )
840+
841
842 def _process_date_view(request, summit, attendee, date):
843 if 'rooms' in request.GET:
844 roomnames = request.GET.get('rooms', '').split(',')
845 rooms = list(summit.room_set.filter(name__in=roomnames, type='open'))
846 if request.user.is_authenticated() and request.user.is_staff:
847- rooms += list(summit.room_set.filter(name__in=roomnames, type='private'))
848+ rooms += list(
849+ summit.room_set.filter(
850+ name__in=roomnames,
851+ type='private'
852+ )
853+ )
854 else:
855 rooms = None
856- schedule = schedule_factory(request, summit, attendee, room=rooms, date=date)
857+ schedule = schedule_factory(
858+ request,
859+ summit,
860+ attendee,
861+ room=rooms,
862+ date=date
863+ )
864
865 if request.method == 'POST':
866 return schedule.save_change()
867@@ -183,25 +219,42 @@
868 'previousday': viewdate - day,
869 'can_change_agenda': summit.can_change_agenda(attendee),
870 }
871- converted_date = summit.delocalize(datetime.datetime.strptime(date, "%Y-%m-%d"))
872- if 'edit' in request.GET or Slot.objects.filter(summit=summit, start_utc__gte=converted_date, end_utc__lte=converted_date+datetime.timedelta(days=1)).count() > 0:
873+ converted_date = summit.delocalize(
874+ datetime.datetime.strptime(date, "%Y-%m-%d")
875+ )
876+ if 'edit' in request.GET or Slot.objects.filter(
877+ summit=summit,
878+ start_utc__gte=converted_date,
879+ end_utc__lte=converted_date+datetime.timedelta(days=1)
880+ ).count() > 0:
881 schedule.calculate()
882 else:
883 return render_to_response("schedule/nosession.html", context,
884- context_instance=RequestContext(request))
885+ context_instance=RequestContext(request))
886 return render_to_response("schedule/schedule.html", context,
887 context_instance=RequestContext(request))
888
889+
890 @summit_required
891 def next_table(request, summit, attendee):
892 if 'rooms' in request.GET:
893 roomnames = request.GET.get('rooms', '').split(',')
894 rooms = list(summit.room_set.filter(name__in=roomnames, type='open'))
895 if request.user.is_authenticated() and request.user.is_staff:
896- rooms += list(summit.room_set.filter(name__in=roomnames, type='private'))
897+ rooms += list(
898+ summit.room_set.filter(
899+ name__in=roomnames, type='private'
900+ )
901+ )
902 else:
903 rooms = None
904- schedule = Schedule.from_request(request, summit, attendee, room=rooms, nextonly=True)
905+ schedule = Schedule.from_request(
906+ request,
907+ summit,
908+ attendee,
909+ room=rooms,
910+ nextonly=True
911+ )
912
913 schedule.calculate()
914
915@@ -214,6 +267,7 @@
916 return render_to_response("schedule/nextsession_table.html", context,
917 context_instance=RequestContext(request))
918
919+
920 @summit_required
921 def next_session(request, summit, attendee):
922 url_content = request.GET.urlencode(safe='_:')
923@@ -226,16 +280,21 @@
924 return render_to_response("schedule/nextsession.html", context,
925 context_instance=RequestContext(request))
926
927+
928 @summit_required
929 def by_room(request, summit, attendee, room_name):
930 schedule = SortedDict()
931 multislot_meetings = SortedDict()
932
933 room = get_object_or_404(Room, name=room_name, summit=summit)
934-
935+
936 for slot in summit.slot_set.all().order_by('start_utc'):
937
938- if not (slot.type == 'open' or slot.type == 'plenary' or slot.type == 'lunch'):
939+ if not (
940+ slot.type == 'open' or
941+ slot.type == 'plenary' or
942+ slot.type == 'lunch'
943+ ):
944 continue
945 if not slot in schedule:
946 schedule[slot] = SortedDict()
947@@ -246,7 +305,7 @@
948 if count == 1:
949 del multislot_meetings[agenda]
950 else:
951- multislot_meetings[agenda] = count -1
952+ multislot_meetings[agenda] = count - 1
953
954 # Add meetings from this slot
955 for agenda in slot.agenda_set.filter(room=room).select_related():
956@@ -277,7 +336,11 @@
957
958 for slot in summit.slot_set.all().order_by('start_utc'):
959
960- if not (slot.type == 'open' or slot.type == 'plenary' or slot.type == 'lunch'):
961+ if not (
962+ slot.type == 'open' or
963+ slot.type == 'plenary' or
964+ slot.type == 'lunch'
965+ ):
966 continue
967 if not slot in schedule:
968 schedule[slot] = SortedDict()
969@@ -288,10 +351,12 @@
970 if count == 1:
971 del multislot_meetings[agenda]
972 else:
973- multislot_meetings[agenda] = count -1
974+ multislot_meetings[agenda] = count - 1
975
976 # Add meetings from this slot
977- for agenda in slot.agenda_set.filter(meeting__tracks=track).select_related().order_by('room__name'):
978+ for agenda in slot.agenda_set.filter(
979+ meeting__tracks=track
980+ ).select_related().order_by('room__name'):
981 if not agenda.meeting.private or attendee in agenda.meeting.attendees:
982 schedule[slot][agenda.room] = agenda
983 if agenda.meeting.slots > 1:
984@@ -309,16 +374,25 @@
985 return render_to_response("schedule/by_track.html", context,
986 context_instance=RequestContext(request))
987
988+
989 @summit_required
990 def by_participant(request, summit, attendee, username):
991 schedule = SortedDict()
992 multislot_meetings = SortedDict()
993
994- participant = get_object_or_404(Attendee, user__username=username, summit=summit)
995+ participant = get_object_or_404(
996+ Attendee,
997+ user__username=username,
998+ summit=summit
999+ )
1000
1001 for slot in summit.slot_set.all().order_by('start_utc'):
1002
1003- if not (slot.type == 'open' or slot.type == 'plenary' or slot.type == 'lunch'):
1004+ if not (
1005+ slot.type == 'open' or
1006+ slot.type == 'plenary' or
1007+ slot.type == 'lunch'
1008+ ):
1009 continue
1010 if not slot in schedule:
1011 schedule[slot] = SortedDict()
1012@@ -329,10 +403,18 @@
1013 if count == 1:
1014 del multislot_meetings[agenda]
1015 else:
1016- multislot_meetings[agenda] = count -1
1017+ multislot_meetings[agenda] = count - 1
1018
1019 # Add meetings from this slot
1020- for agenda in slot.agenda_set.filter(Q(meeting__participant__attendee=participant) | Q(meeting__drafter=participant) | Q(meeting__assignee=participant)).select_related().order_by('room__name'):
1021+ for agenda in slot.agenda_set.filter(
1022+ Q(
1023+ meeting__participant__attendee=participant
1024+ ) | Q(
1025+ meeting__drafter=participant
1026+ ) | Q(
1027+ meeting__assignee=participant
1028+ )
1029+ ).select_related().order_by('room__name'):
1030 if not agenda.meeting.private or attendee in agenda.meeting.attendees:
1031 schedule[slot][agenda.room] = agenda
1032 if agenda.meeting.slots > 1:
1033@@ -350,6 +432,7 @@
1034 return render_to_response("schedule/by_participant.html", context,
1035 context_instance=RequestContext(request))
1036
1037+
1038 @summit_only_required
1039 def tracks(request, summit):
1040
1041@@ -359,6 +442,7 @@
1042 return render_to_response("schedule/tracks.html", context,
1043 context_instance=RequestContext(request))
1044
1045+
1046 @summit_required
1047 def meeting(request, summit, attendee, meeting_id, meeting_slug):
1048 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
1049@@ -366,11 +450,13 @@
1050 raise Http404
1051 return _show_meeting(request, summit, meeting, attendee)
1052
1053+
1054 @summit_required
1055 def private_meeting(request, summit, attendee, private_key, meeting_slug):
1056 meeting = get_object_or_404(summit.meeting_set, private_key=private_key)
1057 return _show_meeting(request, summit, meeting, attendee)
1058
1059+
1060 def _show_meeting(request, summit, meeting, attendee):
1061 agendaitems = meeting.agenda_set.all()
1062 participants = meeting.participant_set.all()
1063@@ -378,29 +464,40 @@
1064 tracks = meeting.tracks.all()
1065 user_is_attending = attendee is not None and attendee in meeting.attendees
1066 user_is_participating = attendee is not None and attendee in [p.attendee for p in participants if not p.from_launchpad]
1067-
1068+
1069 if attendee == meeting.drafter:
1070 drafter = True
1071 else:
1072 drafter = False
1073-
1074+
1075 context = {
1076 'summit': summit,
1077- 'meeting':meeting,
1078- 'agenda_items':agendaitems,
1079- 'participants':participants,
1080+ 'meeting': meeting,
1081+ 'agenda_items': agendaitems,
1082+ 'participants': participants,
1083 'attendees': attendees,
1084 'user_is_attending': user_is_attending,
1085 'user_is_participating': user_is_participating,
1086- 'tracks':tracks,
1087+ 'tracks': tracks,
1088 'ETHERPAD_HOST': summit.etherpad,
1089 'summit_organizer': summit.is_organizer(attendee),
1090 'scheduler': summit.can_change_agenda(attendee),
1091 'is_scheduler': summit.is_scheduler(attendee),
1092 'drafter': drafter,
1093 }
1094- return render_to_response("schedule/meeting.html", context,
1095- context_instance=RequestContext(request))
1096+ if summit.virtual_summit or meeting.virtual_meeting:
1097+ return render_to_response(
1098+ "schedule/virtual_meeting.html",
1099+ context,
1100+ context_instance=RequestContext(request)
1101+ )
1102+ else:
1103+ return render_to_response(
1104+ "schedule/meeting.html",
1105+ context,
1106+ context_instance=RequestContext(request)
1107+ )
1108+
1109
1110 @summit_required
1111 def share_meeting(request, summit, attendee, meeting_id, meeting_slug):
1112@@ -409,30 +506,62 @@
1113 # check if the user should be able to see this private meeting
1114 if attendee is None:
1115 raise Http404
1116-
1117+
1118 attendee_allowed = False
1119 for a in meeting.attendees:
1120 if a.user.pk == attendee.user.pk:
1121 meeting.share()
1122- return HttpResponseRedirect(reverse(private_meeting, args=[summit.name, meeting.private_key, meeting_slug]))
1123+ return HttpResponseRedirect(
1124+ reverse(
1125+ private_meeting,
1126+ args=[summit.name, meeting.private_key, meeting_slug]
1127+ )
1128+ )
1129 raise Http404
1130- return HttpResponseRedirect(reverse(meeting, summit.name, meeting.id, meeting_slug))
1131-
1132+ return HttpResponseRedirect(
1133+ reverse(
1134+ meeting,
1135+ summit.name,
1136+ meeting.id,
1137+ meeting_slug
1138+ )
1139+ )
1140+
1141+
1142 @summit_attendee_required
1143 def register(request, summit, attendee, meeting_id, meeting_slug):
1144 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
1145 user_is_attending = attendee is not None and attendee in meeting.attendees
1146 if not user_is_attending:
1147- meeting.participant_set.create(attendee=attendee, participation = 'ATTENDING', from_launchpad=False)
1148-
1149- return HttpResponseRedirect(reverse('summit.schedule.views.meeting', args=(summit.name, meeting.id, meeting_slug)))
1150+ meeting.participant_set.create(
1151+ attendee=attendee,
1152+ participation='ATTENDING',
1153+ from_launchpad=False
1154+ )
1155+
1156+ return HttpResponseRedirect(
1157+ reverse(
1158+ 'summit.schedule.views.meeting',
1159+ args=(summit.name, meeting.id, meeting_slug)
1160+ )
1161+ )
1162+
1163
1164 @summit_attendee_required
1165 def unregister(request, summit, attendee, meeting_id, meeting_slug):
1166 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
1167- meeting.participant_set.filter(attendee=attendee, from_launchpad=False).delete()
1168-
1169- return HttpResponseRedirect(reverse('summit.schedule.views.meeting', args=(summit.name, meeting.id, meeting_slug)))
1170+ meeting.participant_set.filter(
1171+ attendee=attendee,
1172+ from_launchpad=False
1173+ ).delete()
1174+
1175+ return HttpResponseRedirect(
1176+ reverse(
1177+ 'summit.schedule.views.meeting',
1178+ args=(summit.name, meeting.id, meeting_slug)
1179+ )
1180+ )
1181+
1182
1183 @summit_only_required
1184 def csv(request, summit):
1185@@ -442,70 +571,82 @@
1186 return HttpResponse(schedule.as_csv(),
1187 mimetype='text/csv')
1188
1189+
1190 @summit_only_required
1191 def ical(request, summit):
1192 """Return any list events as an ical"""
1193 schedule = Schedule.from_request(request, summit)
1194 schedule.calculate()
1195-
1196+
1197 filename = "%s.ical" % summit.name.replace(' ', '-').lower()
1198 response = HttpResponse(mimetype='text/calendar')
1199 response['Content-Disposition'] = 'attachment; filename=%s' % filename.encode('ascii', 'replace')
1200 response.write(schedule.as_ical())
1201 return response
1202
1203+
1204 @summit_only_required
1205 def user_ical(request, summit, username):
1206 """Returns a user's registered events as an ical"""
1207 schedule = Schedule.from_request(request, summit)
1208 schedule.calculate()
1209-
1210+
1211 filename = "%s_%s.ical" % (summit.name, username)
1212 response = HttpResponse(mimetype='text/calendar')
1213 response['Content-Disposition'] = 'attachment; filename=%s' % filename.replace(' ', '-').lower().encode('ascii', 'replace')
1214 response.write(schedule.as_ical(only_username=username))
1215 return response
1216-
1217+
1218+
1219 @summit_only_required
1220 def user_private_ical(request, summit, secret_key):
1221 """Returns a user's registered events as an ical"""
1222 attendee = get_object_or_404(Attendee, secret_key_id=secret_key)
1223 schedule = Schedule.from_request(request, summit, show_private=True)
1224 schedule.calculate()
1225-
1226+
1227 response = HttpResponse(mimetype='text/calendar')
1228 response['Content-Disposition'] = 'attachment; filename=my_schedule_%s.ical' % attendee.secret_key
1229- response.write(schedule.as_ical(only_username=attendee.user.username, show_private=True))
1230+ response.write(
1231+ schedule.as_ical(
1232+ only_username=attendee.user.username,
1233+ show_private=True
1234+ )
1235+ )
1236 return response
1237-
1238+
1239+
1240 @summit_only_required
1241 def room_ical(request, summit, room_name):
1242 """Returns a room's events as an ical"""
1243 schedule = Schedule.from_request(request, summit)
1244 schedule.calculate()
1245-
1246+
1247 filename = "%s_%s.ical" % (summit.name, room_name)
1248 response = HttpResponse(mimetype='text/calendar')
1249 response['Content-Disposition'] = 'attachment; filename=%s' % filename.replace(' ', '-').lower().encode('ascii', 'replace')
1250 response.write(schedule.as_ical(only_room=room_name))
1251 return response
1252-
1253+
1254+
1255 @summit_only_required
1256 def track_ical(request, summit, track_slug):
1257 """Returns a track's events as an ical"""
1258 schedule = Schedule.from_request(request, summit)
1259 schedule.calculate()
1260-
1261+
1262 filename = "%s_%s.ical" % (summit.name, track_slug)
1263 response = HttpResponse(mimetype='text/calendar')
1264 response['Content-Disposition'] = 'attachment; filename=%s' % filename.replace(' ', '-').lower().encode('ascii', 'replace')
1265 response.write(schedule.as_ical(only_track=track_slug))
1266 return response
1267-
1268+
1269+
1270 def logout_view(request):
1271 logout(request)
1272 return HttpResponseRedirect('/')
1273
1274+
1275 @summit_required
1276 def mobile(request, summit, attendee):
1277 context = {
1278@@ -514,6 +655,7 @@
1279 }
1280 return render_to_response("schedule/mobile.html", context, RequestContext(request))
1281
1282+
1283 def past(request):
1284 pastsummit = Summit.on_site.filter(date_end__lte=datetime.date.today())
1285 context = {
1286@@ -522,15 +664,26 @@
1287 return render_to_response("schedule/past_summit.html", context,
1288 context_instance=RequestContext(request))
1289
1290+
1291 @summit_attendee_required
1292 def create_meeting(request, summit, attendee):
1293
1294 if not summit.is_organizer(attendee):
1295- return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))
1296+ return HttpResponseRedirect(
1297+ reverse(
1298+ 'summit.schedule.views.summit',
1299+ args=(summit.name,)
1300+ )
1301+ )
1302 else:
1303- meeting = Meeting(summit=summit, approver=attendee, drafter=attendee, approved='APPROVED')
1304-
1305- if request.method == 'POST':
1306+ meeting = Meeting(
1307+ summit=summit,
1308+ approver=attendee,
1309+ drafter=attendee,
1310+ approved='APPROVED'
1311+ )
1312+
1313+ if request.method == 'POST':
1314 form = CreateMeeting(data=request.POST, instance=meeting)
1315 if form.is_valid():
1316 form.save()
1317@@ -542,15 +695,21 @@
1318 'summit': summit,
1319 'form': form,
1320 }
1321- return render_to_response('schedule/create_meeting.html',
1322+ return render_to_response('schedule/create_meeting.html',
1323 context, RequestContext(request))
1324
1325+
1326 @summit_attendee_required
1327 def propose_meeting(request, summit, attendee):
1328
1329- meeting = Meeting(summit=summit, drafter=attendee, private=False, approved='PENDING')
1330+ meeting = Meeting(
1331+ summit=summit,
1332+ drafter=attendee,
1333+ private=False,
1334+ approved='PENDING'
1335+ )
1336
1337- if request.method == 'POST':
1338+ if request.method == 'POST':
1339 form = ProposeMeeting(data=request.POST, instance=meeting)
1340 if form.is_valid():
1341 form.save()
1342@@ -562,17 +721,29 @@
1343 'summit': summit,
1344 'form': form,
1345 }
1346- return render_to_response('schedule/propose_meeting.html',
1347+ return render_to_response('schedule/propose_meeting.html',
1348 context, RequestContext(request))
1349-
1350+
1351+
1352 @summit_attendee_required
1353-def organizer_edit_meeting(request, summit, attendee, meeting_id, meeting_slug):
1354+def organizer_edit_meeting(
1355+ request,
1356+ summit,
1357+ attendee,
1358+ meeting_id,
1359+ meeting_slug
1360+):
1361 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
1362-
1363+
1364 if not summit.is_organizer(attendee):
1365- return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))
1366+ return HttpResponseRedirect(
1367+ reverse(
1368+ 'summit.schedule.views.summit',
1369+ args=(summit.name,)
1370+ )
1371+ )
1372 else:
1373- if request.method == 'POST':
1374+ if request.method == 'POST':
1375 form = OrganizerEditMeeting(data=request.POST, instance=meeting)
1376 if form.is_valid():
1377 form.save()
1378@@ -584,17 +755,23 @@
1379 'summit': summit,
1380 'form': form,
1381 }
1382- return render_to_response('schedule/org_edit_meeting.html',
1383+ return render_to_response('schedule/org_edit_meeting.html',
1384 context, RequestContext(request))
1385
1386+
1387 @summit_attendee_required
1388 def edit_meeting(request, summit, attendee, meeting_id, meeting_slug):
1389 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
1390-
1391+
1392 if attendee != meeting.drafter:
1393- return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))
1394+ return HttpResponseRedirect(
1395+ reverse(
1396+ 'summit.schedule.views.summit',
1397+ args=(summit.name,)
1398+ )
1399+ )
1400 else:
1401- if request.method == 'POST':
1402+ if request.method == 'POST':
1403 form = EditMeeting(data=request.POST, instance=meeting)
1404 if form.is_valid():
1405 form.save()
1406@@ -606,14 +783,55 @@
1407 'summit': summit,
1408 'form': form,
1409 }
1410- return render_to_response('schedule/edit_meeting.html',
1411- context, RequestContext(request))
1412+ return render_to_response('schedule/edit_meeting.html',
1413+ context, RequestContext(request))
1414+
1415+
1416+@summit_attendee_required
1417+def edit_meeting_hangout(
1418+ request,
1419+ summit,
1420+ attendee,
1421+ meeting_id,
1422+ meeting_slug
1423+):
1424+ meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
1425+ # TODO: Add logic that prevents this view from being accessed if the
1426+ # Summit or meeting is not virtual
1427+ if not summit.is_organizer(attendee) and attendee != meeting.drafter:
1428+ return HttpResponseRedirect(
1429+ reverse(
1430+ 'summit.schedule.views.summit',
1431+ args=(summit.name,)
1432+ )
1433+ )
1434+ else:
1435+ if request.method == 'POST':
1436+ form = EditMeetingHangout(data=request.POST, instance=meeting)
1437+ if form.is_valid():
1438+ form.save()
1439+ return HttpResponseRedirect(meeting.meeting_page_url)
1440+ else:
1441+ form = EditMeetingHangout(instance=meeting)
1442+
1443+ context = {
1444+ 'summit': summit,
1445+ 'form': form,
1446+ }
1447+ return render_to_response('schedule/edit_hangout.html',
1448+ context, RequestContext(request))
1449+
1450
1451 @summit_required
1452 def review_pending(request, summit, attendee):
1453
1454 if not summit.is_organizer(attendee):
1455- return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))
1456+ return HttpResponseRedirect(
1457+ reverse(
1458+ 'summit.schedule.views.summit',
1459+ args=(summit.name,)
1460+ )
1461+ )
1462 else:
1463 schedule = SortedDict()
1464
1465@@ -632,12 +850,18 @@
1466 return render_to_response("schedule/review.html", context,
1467 context_instance=RequestContext(request))
1468
1469+
1470 @summit_required
1471 def meeting_review(request, summit, attendee, meeting_id):
1472 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
1473
1474 if not summit.is_organizer(attendee):
1475- return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))
1476+ return HttpResponseRedirect(
1477+ reverse(
1478+ 'summit.schedule.views.summit',
1479+ args=(summit.name,)
1480+ )
1481+ )
1482 else:
1483 if request.method == 'POST':
1484 form = MeetingReview(data=request.POST, instance=meeting)
1485@@ -656,12 +880,19 @@
1486 return render_to_response('schedule/meeting_review.html',
1487 context, RequestContext(request))
1488
1489+
1490 @summit_required
1491 def created_meetings(request, summit, attendee, username):
1492
1493- drafter = get_object_or_404(Attendee, summit=summit, user__username=username)
1494+ drafter = get_object_or_404(
1495+ Attendee,
1496+ summit=summit,
1497+ user__username=username
1498+ )
1499 if attendee is None or attendee.id != drafter.id:
1500- meetings = summit.meeting_set.filter(drafter=drafter).exclude(private=True)
1501+ meetings = summit.meeting_set.filter(
1502+ drafter=drafter
1503+ ).exclude(private=True)
1504 else:
1505 meetings = summit.meeting_set.filter(drafter=drafter)
1506
1507@@ -674,12 +905,18 @@
1508 return render_to_response("schedule/mine.html", context,
1509 context_instance=RequestContext(request))
1510
1511+
1512 @summit_required
1513 def meeting_copy(request, summit, attendee, meeting_id, meeting_slug):
1514 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
1515
1516 if not summit.can_change_agenda(attendee):
1517- return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))
1518+ return HttpResponseRedirect(
1519+ reverse(
1520+ 'summit.schedule.views.summit',
1521+ args=(summit.name,)
1522+ )
1523+ )
1524 else:
1525 if request.method == 'POST':
1526 form = CreateMeeting(instance=meeting, data=request.POST)
1527@@ -692,7 +929,6 @@
1528 meeting = form.save()
1529 meeting_id = meeting.id
1530 return HttpResponseRedirect(meeting.meeting_page_url)
1531-
1532 else:
1533 form = CreateMeeting(instance=meeting)
1534
1535@@ -700,19 +936,23 @@
1536 'summit': summit,
1537 'form': form,
1538 }
1539-
1540- return render_to_response('schedule/create_meeting.html',
1541+
1542+ return render_to_response('schedule/create_meeting.html',
1543 context, RequestContext(request))
1544
1545+
1546 @summit_attendee_required
1547 def attend_meeting(request, summit, attendee, meeting_id):
1548 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
1549
1550 try:
1551- participant = Participant.objects.get(attendee=attendee, meeting=meeting)
1552+ participant = Participant.objects.get(
1553+ attendee=attendee,
1554+ meeting=meeting
1555+ )
1556 except Participant.DoesNotExist:
1557 participant = Participant(attendee=attendee, meeting=meeting)
1558-
1559+
1560 if request.method == 'POST':
1561 form = AttendMeeting(data=request.POST, instance=participant)
1562 if form.is_valid():
1563@@ -731,44 +971,79 @@
1564 return render_to_response('schedule/attend.html',
1565 context, RequestContext(request))
1566
1567+
1568 @summit_required
1569 def attendee_review(request, summit, attendee, meeting_slug, meeting_id):
1570 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
1571
1572 if not summit.is_organizer(attendee) and attendee != meeting.drafter:
1573- return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))
1574+ return HttpResponseRedirect(
1575+ reverse(
1576+ 'summit.schedule.views.summit',
1577+ args=(summit.name,)
1578+ )
1579+ )
1580 else:
1581 participants = meeting.participant_set.all()
1582
1583 context = {
1584 'summit': summit,
1585- 'meeting':meeting,
1586- 'participants':participants,
1587+ 'meeting': meeting,
1588+ 'participants': participants,
1589 'summit_organizer': summit.is_organizer(attendee),
1590
1591 }
1592 return render_to_response("schedule/attendees.html", context,
1593 context_instance=RequestContext(request))
1594
1595+
1596 @summit_attendee_required
1597-def organizer_edit_attendees(request, summit, logged_in_user, username, meeting_id):
1598+def organizer_edit_attendees(
1599+ request,
1600+ summit,
1601+ logged_in_user,
1602+ username,
1603+ meeting_id
1604+):
1605 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
1606- attendee = get_object_or_404(Attendee, summit=summit, user__username=username)
1607+ attendee = get_object_or_404(
1608+ Attendee,
1609+ summit=summit,
1610+ user__username=username
1611+ )
1612 meeting_slug = get_object_or_404(Meeting, summit=summit, id=meeting_id)
1613
1614- if not summit.is_organizer(logged_in_user) and logged_in_user != meeting.drafter:
1615- return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))
1616+ if not summit.is_organizer(
1617+ logged_in_user
1618+ ) and logged_in_user != meeting.drafter:
1619+ return HttpResponseRedirect(
1620+ reverse(
1621+ 'summit.schedule.views.summit',
1622+ args=(summit.name,)
1623+ )
1624+ )
1625 else:
1626 try:
1627- participant = Participant.objects.get(attendee=attendee, meeting=meeting)
1628+ participant = Participant.objects.get(
1629+ attendee=attendee,
1630+ meeting=meeting
1631+ )
1632 except Participant.DoesNotExist:
1633 participant = Participant(attendee=attendee, meeting=meeting)
1634-
1635+
1636 if request.method == 'POST':
1637- form = OrganizerChangeAttend(data=request.POST, instance=participant)
1638+ form = OrganizerChangeAttend(
1639+ data=request.POST,
1640+ instance=participant
1641+ )
1642 if form.is_valid():
1643 form.save()
1644- return HttpResponseRedirect(reverse('summit.schedule.views.attendee_review', args=(summit.name, meeting.id, meeting.name)))
1645+ return HttpResponseRedirect(
1646+ reverse(
1647+ 'summit.schedule.views.attendee_review',
1648+ args=(summit.name, meeting.id, meeting.name)
1649+ )
1650+ )
1651 else:
1652 form = OrganizerChangeAttend(instance=participant)
1653
1654@@ -784,11 +1059,22 @@
1655
1656
1657 @summit_attendee_required
1658-def delete_meeting_confirm(request, summit, attendee, meeting_id, meeting_slug):
1659+def delete_meeting_confirm(
1660+ request,
1661+ summit,
1662+ attendee,
1663+ meeting_id,
1664+ meeting_slug
1665+):
1666 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
1667-
1668+
1669 if not attendee.user in summit.schedulers.all() and not attendee.user.has_perm('schedule.change_agenda'):
1670- return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))
1671+ return HttpResponseRedirect(
1672+ reverse(
1673+ 'summit.schedule.views.summit',
1674+ args=(summit.name,)
1675+ )
1676+ )
1677
1678 context = {
1679 'summit': summit,
1680@@ -801,18 +1087,29 @@
1681
1682 @summit_attendee_required
1683 def delete_meeting(request, summit, attendee, meeting_id, meeting_slug):
1684- meeting = get_object_or_404(summit.meeting_set, pk = meeting_id)
1685+ meeting = get_object_or_404(summit.meeting_set, pk=meeting_id)
1686 if not attendee.user in summit.schedulers.all() and not attendee.user.has_perm('schedule.change_agenda'):
1687- return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))
1688+ return HttpResponseRedirect(
1689+ reverse(
1690+ 'summit.schedule.views.summit',
1691+ args=(summit.name,)
1692+ )
1693+ )
1694 else:
1695 meeting.approved = 'REMOVED'
1696 meeting.save()
1697 meeting.agenda_set.all().delete()
1698- return HttpResponseRedirect(reverse('summit.schedule.views.delete_confirmed', args=(summit.name,)))
1699+ return HttpResponseRedirect(
1700+ reverse(
1701+ 'summit.schedule.views.delete_confirmed',
1702+ args=(summit.name,)
1703+ )
1704+ )
1705+
1706
1707 def delete_confirmed(request, summit_name):
1708 summit = get_object_or_404(Summit, name=summit_name)
1709-
1710+
1711 context = {
1712 'summit': summit
1713 }
1714
1715=== modified file 'summit/urls.py'
1716--- summit/urls.py 2012-10-26 09:32:11 +0000
1717+++ summit/urls.py 2013-02-22 02:06:23 +0000
1718@@ -16,7 +16,6 @@
1719
1720 from django.conf.urls.defaults import *
1721 from django.conf import settings
1722-import ubuntu_website
1723
1724 from common.views import login_failure
1725
1726@@ -24,13 +23,15 @@
1727 admin.autodiscover()
1728
1729
1730-urlpatterns = patterns('',
1731+urlpatterns = patterns(
1732+ '',
1733 (r'^$', 'summit.common.views.index'),
1734 (r'^admin/', admin.site.urls),
1735 (r'^api/', include('services.urls')),
1736 )
1737
1738-urlpatterns += patterns('django_openid_auth.views',
1739+urlpatterns += patterns(
1740+ 'django_openid_auth.views',
1741 url(r'^openid/login/$', 'login_begin', name='openid-login',
1742 kwargs={'render_failure': login_failure}),
1743 url(r'^openid/complete/$', 'login_complete', name='openid-complete',
1744@@ -38,19 +39,17 @@
1745 url(r'^openid/logo.gif$', 'logo', name='openid-logo'),
1746 )
1747
1748-urlpatterns += patterns('summit.sponsor.views',
1749+urlpatterns += patterns(
1750+ 'summit.sponsor.views',
1751 (r'^(?P<summit_name>[\w-]+)/sponsorship/$', 'sponsorship'),
1752 (r'^(?P<summit_name>[\w-]+)/sponsorship/done/$', 'done'),
1753 (r'^(?P<summit_name>[\w-]+)/sponsorship/review/$', 'review_list'),
1754-
1755 (r'^(?P<summit_name>[\w-]+)/suggestsponsorship/$', 'suggestsponsorship'),
1756 (r'^(?P<summit_name>[\w-]+)/suggestsponsorship/done/$', 'suggestiondone'),
1757-
1758 (r'^(?P<summit_name>[\w-]+)/nonlaunchpadsponsorship/$',
1759 'nonlaunchpadsponsorship'),
1760 (r'^(?P<summit_name>[\w-]+)/nonlaunchpadsponsorship/done/$',
1761 'nonlaunchpaddone'),
1762-
1763 (r'^(?P<summit_name>[\w-]+)/sponsorship/review/(?P<sponsorship_id>[0-9]+)$',
1764 'review'),
1765 (r'^(?P<summit_name>[\w-]+)/suggestedsponsorship/review/(?P<sponsorship_id>[0-9]+)$',
1766@@ -61,7 +60,8 @@
1767 (r'^(?P<summit_name>[\w-]+)/sponsorship/export/$', 'export'),
1768 )
1769
1770-urlpatterns += patterns('summit.schedule.views',
1771+urlpatterns += patterns(
1772+ 'summit.schedule.views',
1773 url(r'^today/(?P<summit_name>[\w-]+)/$', 'today_view', name='today'),
1774 url(r'^past/', 'past', name='past'),
1775 url(r'^logout$', 'logout_view', name='logout'),
1776@@ -69,42 +69,66 @@
1777 (r'^(?P<summit_name>[\w-]+)/mobile/$', 'mobile'),
1778 (r'^(?P<summit_name>[\w-]+)/search/$', 'search'),
1779 (r'^(?P<summit_name>[\w-]+)/propose_meeting/$', 'propose_meeting'),
1780- (r'^(?P<summit_name>[\w-]+)/edit_meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', 'edit_meeting'),
1781+ (r'^(?P<summit_name>[\w-]+)/edit_meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
1782+ 'edit_meeting'),
1783 (r'^(?P<summit_name>[\w-]+)/review/$', 'review_pending'),
1784- (r'^(?P<summit_name>[\w-]+)/review_meeting/(?P<meeting_id>\d+)/$', 'meeting_review'),
1785- (r'^(?P<summit_name>[\w-]+)/attend_meeting/(?P<meeting_id>\d+)/$', 'attend_meeting'),
1786- (r'^(?P<summit_name>[\w-]+)/edit_attendee/(?P<meeting_id>\d+)/(?P<username>[%+\.\w-]+)/$', 'organizer_edit_attendees'),
1787+ (r'^(?P<summit_name>[\w-]+)/review_meeting/(?P<meeting_id>\d+)/$',
1788+ 'meeting_review'),
1789+ (r'^(?P<summit_name>[\w-]+)/attend_meeting/(?P<meeting_id>\d+)/$',
1790+ 'attend_meeting'),
1791+ (r'^(?P<summit_name>[\w-]+)/edit_attendee/(?P<meeting_id>\d+)/(?P<username>[%+\.\w-]+)/$',
1792+ 'organizer_edit_attendees'),
1793 (r'^(?P<summit_name>[\w-]+)/create_meeting/$', 'create_meeting'),
1794- (r'^(?P<summit_name>[\w-]+)/edit_mtg/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', 'organizer_edit_meeting'),
1795- (r'^(?P<summit_name>[\w-]+)/confirm_del_mtg/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', 'delete_meeting_confirm'),
1796- (r'^(?P<summit_name>[\w-]+)/del_mtg/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', 'delete_meeting'),
1797+ (r'^(?P<summit_name>[\w-]+)/edit_mtg/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
1798+ 'organizer_edit_meeting'),
1799+ (r'^(?P<summit_name>[\w-]+)/hangout/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
1800+ 'edit_meeting_hangout'),
1801+ (r'^(?P<summit_name>[\w-]+)/confirm_del_mtg/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
1802+ 'delete_meeting_confirm'),
1803+ (r'^(?P<summit_name>[\w-]+)/del_mtg/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
1804+ 'delete_meeting'),
1805 (r'^(?P<summit_name>[\w-]+)/deleted/$', 'delete_confirmed'),
1806- (r'^(?P<summit_name>[\w-]+)/attendee_review/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', 'attendee_review'),
1807+ (r'^(?P<summit_name>[\w-]+)/attendee_review/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
1808+ 'attendee_review'),
1809 (r'^(?P<summit_name>[\w-]+)/tracks$', 'tracks'),
1810 (r'^(?P<summit_name>[\w-]+)/next$', 'next_session'),
1811 (r'^(?P<summit_name>[\w-]+)/next_table$', 'next_table'),
1812- (r'^(?P<summit_name>[\w-]+)/(?P<username>[%+\.\w-]+)/meetings$', 'created_meetings'),
1813+ (r'^(?P<summit_name>[\w-]+)/(?P<username>[%+\.\w-]+)/meetings$',
1814+ 'created_meetings'),
1815 (r'^(?P<summit_name>[\w-]+)/(?P<date>[\d-]+)/$', 'daily_schedule'),
1816 (r'^(?P<summit_name>[\w-]+)/(?P<date>[\d-]+)/display$', 'by_date'),
1817 (r'^(?P<summit_name>[\w-]+)/(?P<room_name>[%+\.\w-]+)/$', 'by_room'),
1818- (r'^(?P<summit_name>[\w-]+)/track/(?P<track_slug>[%+\.\w-]+)/$', 'by_track'),
1819- (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/\+share$', 'share_meeting'),
1820- (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/\+register', 'register'),
1821- (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/\+unregister', 'unregister'),
1822- (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', 'meeting'),
1823- (r'^(?P<summit_name>[\w-]+)/private/(?P<private_key>[0-9a-f]{32})/(?P<meeting_slug>[%+\.\w-]+)/$', 'private_meeting'),
1824- (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/copy/$', 'meeting_copy'),
1825+ (r'^(?P<summit_name>[\w-]+)/track/(?P<track_slug>[%+\.\w-]+)/$',
1826+ 'by_track'),
1827+ (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/\+share$',
1828+ 'share_meeting'),
1829+ (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/\+register',
1830+ 'register'),
1831+ (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/\+unregister',
1832+ 'unregister'),
1833+ (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
1834+ 'meeting'),
1835+ (r'^(?P<summit_name>[\w-]+)/private/(?P<private_key>[0-9a-f]{32})/(?P<meeting_slug>[%+\.\w-]+)/$',
1836+ 'private_meeting'),
1837+ (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/copy/$',
1838+ 'meeting_copy'),
1839 (r'^(?P<summit_name>[\w-]+)\.csv$', 'csv'),
1840 (r'^(?P<summit_name>[\w-]+)\.ical$', 'ical'),
1841- (r'^(?P<summit_name>[\w-]+)/participant/(?P<username>[%+\.\w-]+)/$', 'by_participant'),
1842- (r'^(?P<summit_name>[\w-]+)/participant/my_schedule_(?P<secret_key>[0-9a-f]{32})\.ical$', 'user_private_ical'),
1843- (r'^(?P<summit_name>[\w-]+)/participant/(?P<username>[%+\.\w-]+)\.ical$', 'user_ical'),
1844- (r'^(?P<summit_name>[\w-]+)/room/(?P<room_name>[%+\.\w-]+).ical$', 'room_ical'),
1845- (r'^(?P<summit_name>[\w-]+)/track/(?P<track_slug>[%+\.\w-]+).ical$', 'track_ical'),
1846+ (r'^(?P<summit_name>[\w-]+)/participant/(?P<username>[%+\.\w-]+)/$',
1847+ 'by_participant'),
1848+ (r'^(?P<summit_name>[\w-]+)/participant/my_schedule_(?P<secret_key>[0-9a-f]{32})\.ical$',
1849+ 'user_private_ical'),
1850+ (r'^(?P<summit_name>[\w-]+)/participant/(?P<username>[%+\.\w-]+)\.ical$',
1851+ 'user_ical'),
1852+ (r'^(?P<summit_name>[\w-]+)/room/(?P<room_name>[%+\.\w-]+).ical$',
1853+ 'room_ical'),
1854+ (r'^(?P<summit_name>[\w-]+)/track/(?P<track_slug>[%+\.\w-]+).ical$',
1855+ 'track_ical'),
1856 )
1857
1858 if settings.DEBUG or settings.SERVE_STATIC:
1859- urlpatterns += patterns('',
1860+ urlpatterns += patterns(
1861+ '',
1862 (r'^media/(?P<path>.*)$', 'django.views.static.serve',
1863 {'document_root': settings.MEDIA_ROOT}),
1864 (r'^(robots.txt)$', 'django.views.static.serve',

Subscribers

People subscribed via source and target branches