Merge lp:~cjohnston/summit/moves-tests into lp:summit

Proposed by Chris Johnston
Status: Superseded
Proposed branch: lp:~cjohnston/summit/moves-tests
Merge into: lp:summit
Diff against target: 1840 lines (+867/-186)
8 files modified
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/tests/__init__.py (+17/-0)
summit/schedule/views.py (+400/-103)
summit/urls.py (+54/-30)
To merge this branch: bzr merge lp:~cjohnston/summit/moves-tests
Reviewer Review Type Date Requested Status
Summit Hackers Pending
Review via email: mp+149961@code.launchpad.net

This proposal has been superseded by a proposal from 2013-02-22.

To post a comment you must log in.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'summit/schedule/forms.py'
--- summit/schedule/forms.py 2012-08-12 22:32:46 +0000
+++ summit/schedule/forms.py 2013-02-22 01:25:24 +0000
@@ -22,6 +22,7 @@
2222
23from common.forms import RenderableMixin23from common.forms import RenderableMixin
2424
25
25class MultipleAttendeeField(forms.ModelMultipleChoiceField):26class MultipleAttendeeField(forms.ModelMultipleChoiceField):
26 def label_from_instance(self, obj):27 def label_from_instance(self, obj):
27 return u"%s %s (%s)" % (28 return u"%s %s (%s)" % (
@@ -36,12 +37,8 @@
36 required=False)37 required=False)
3738
38 class Media:39 class Media:
39 css = {'all': (40 css = {'all': ('/media/css/colortip-1.0-jquery.css',)}
40 '/media/css/colortip-1.0-jquery.css', 41 js = ('/media/js/colortip-1.0-jquery.js',)
41 )}
42 js = (
43 '/media/js/colortip-1.0-jquery.js',
44 )
4542
46 def __init__(self, *args, **kwargs):43 def __init__(self, *args, **kwargs):
47 if 'instance' in kwargs:44 if 'instance' in kwargs:
@@ -72,6 +69,7 @@
72 old_save_m2m = self.save_m2m69 old_save_m2m = self.save_m2m
73 else:70 else:
74 old_save_m2m = None71 old_save_m2m = None
72
75 def save_m2m():73 def save_m2m():
76 if old_save_m2m is not None:74 if old_save_m2m is not None:
77 old_save_m2m()75 old_save_m2m()
@@ -94,43 +92,102 @@
94class CreateMeeting(MeetingFormBase, RenderableMixin):92class CreateMeeting(MeetingFormBase, RenderableMixin):
95 class Meta:93 class Meta:
96 model = Meeting94 model = Meeting
97 fields = ('title', 'description', 'tracks', 'type', 'private', 'spec_url', 'wiki_url',95 fields = (
98 'pad_url', 'requires_dial_in', 'slots', 'approved', 'video', 'override_break')96 'title',
97 'description',
98 'tracks',
99 'type',
100 'private',
101 'spec_url',
102 'wiki_url',
103 'pad_url',
104 'requires_dial_in',
105 'slots',
106 'approved',
107 'video',
108 'override_break'
109 )
110
99111
100class OrganizerEditMeeting(MeetingFormBase, RenderableMixin):112class OrganizerEditMeeting(MeetingFormBase, RenderableMixin):
101 class Meta:113 class Meta:
102 model = Meeting114 model = Meeting
103 fields = ('title', 'description', 'tracks', 'type', 'private', 'spec_url', 'wiki_url',115 fields = (
104 'pad_url', 'requires_dial_in', 'slots', 'approved', 'video', 'override_break')116 'title',
117 'description',
118 'tracks',
119 'type',
120 'private',
121 'spec_url',
122 'wiki_url',
123 'pad_url',
124 'requires_dial_in',
125 'slots',
126 'approved',
127 'video',
128 'override_break'
129 )
130
105131
106class ProposeMeeting(MeetingFormBase, RenderableMixin):132class ProposeMeeting(MeetingFormBase, RenderableMixin):
107 class Meta:133 class Meta:
108 model = Meeting134 model = Meeting
109 fields = ('title', 'description', 'tracks', 'spec_url', 'wiki_url', 'pad_url')135 fields = (
136 'title',
137 'description',
138 'tracks',
139 'spec_url',
140 'wiki_url',
141 'pad_url'
142 )
110143
111144
112class EditMeeting(MeetingFormBase, RenderableMixin):145class EditMeeting(MeetingFormBase, RenderableMixin):
113 class Meta:146 class Meta:
114 model = Meeting147 model = Meeting
115 fields = ('title', 'description', 'tracks', 'spec_url', 'wiki_url', 'pad_url')148 fields = (
149 'title',
150 'description',
151 'tracks',
152 'spec_url',
153 'wiki_url',
154 'pad_url'
155 )
156
116157
117class MeetingReview(forms.ModelForm, RenderableMixin):158class MeetingReview(forms.ModelForm, RenderableMixin):
118 class Meta:159 class Meta:
119 model = Meeting160 model = Meeting
120 fields = ('approved',)161 fields = ('approved',)
121162
163
122class AttendMeeting(forms.ModelForm, RenderableMixin):164class AttendMeeting(forms.ModelForm, RenderableMixin):
123 class Meta:165 class Meta:
124 model = Participant166 model = Participant
125 fields = ('participation',)167 fields = ('participation',)
168
126 def __init__(self, *args, **kwargs):169 def __init__(self, *args, **kwargs):
127 super(AttendMeeting, self).__init__(*args, **kwargs)170 super(AttendMeeting, self).__init__(*args, **kwargs)
128 self.fields['participation'].choices = ((u'ATTENDING', u'Attending'), (u'INTERESTED', u'Very interested in attending'))171 self.fields['participation'].choices = (
172 (u'ATTENDING', u'Attending'),
173 (u'INTERESTED', u'Very interested in attending')
174 )
175
129176
130class OrganizerChangeAttend(forms.ModelForm, RenderableMixin):177class OrganizerChangeAttend(forms.ModelForm, RenderableMixin):
131 class Meta:178 class Meta:
132 model = Participant179 model = Participant
133 fields = ('participation',)180 fields = ('participation',)
181
134 def __init__(self, *args, **kwargs):182 def __init__(self, *args, **kwargs):
135 super(OrganizerChangeAttend, self).__init__(*args, **kwargs)183 super(OrganizerChangeAttend, self).__init__(*args, **kwargs)
136 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
190class EditMeetingHangout(forms.ModelForm, RenderableMixin):
191 class Meta:
192 model = Meeting
193 fields = ('hangout_url', 'broadcast_url')
137194
=== modified file 'summit/schedule/models/attendeemodel.py'
--- summit/schedule/models/attendeemodel.py 2012-04-30 16:48:43 +0000
+++ summit/schedule/models/attendeemodel.py 2013-02-22 01:25:24 +0000
@@ -45,7 +45,7 @@
45 verbose_name='Willing to be Crew',45 verbose_name='Willing to be Crew',
46 default=False)46 default=False)
47 secret_key_id = models.CharField(max_length=32, blank=True, null=True)47 secret_key_id = models.CharField(max_length=32, blank=True, null=True)
48 48
49 class Meta:49 class Meta:
50 app_label = 'schedule'50 app_label = 'schedule'
51 ordering = ('user__username', 'summit')51 ordering = ('user__username', 'summit')
@@ -86,7 +86,14 @@
86 secret_key = property(get_secret_key, set_secret_key)86 secret_key = property(get_secret_key, set_secret_key)
8787
88 def ical_url(self):88 def ical_url(self):
89 return getattr(settings, 'SITE_ROOT', 'http://summit.ubuntu.com') + reverse('summit.schedule.views.user_private_ical', args=(self.summit.name,self.secret_key))89 return getattr(
90 settings,
91 'SITE_ROOT',
92 'http://summit.ubuntu.com'
93 ) + reverse(
94 'summit.schedule.views.user_private_ical',
95 args=(self.summit.name, self.secret_key)
96 )
9097
91 def update_from_launchpad(self, elem):98 def update_from_launchpad(self, elem):
92 """Update from Launchpad data."""99 """Update from Launchpad data."""
93100
=== modified file 'summit/schedule/models/summitmodel.py'
--- summit/schedule/models/summitmodel.py 2013-02-20 17:33:14 +0000
+++ summit/schedule/models/summitmodel.py 2013-02-22 01:25:24 +0000
@@ -47,6 +47,8 @@
4747
48#Monkey patch for better use in the admin48#Monkey patch for better use in the admin
49User._meta.ordering = ['username']49User._meta.ordering = ['username']
50
51
50def unicode_user(user):52def unicode_user(user):
51 display = []53 display = []
52 if user.first_name:54 if user.first_name:
@@ -56,9 +58,10 @@
56 if len(display) == 0:58 if len(display) == 0:
57 return user.username59 return user.username
58 else:60 else:
59 return user.username + ' (' +' '.join(display) + ')'61 return user.username + ' (' + ' '.join(display) + ')'
60User.__unicode__ = unicode_user62User.__unicode__ = unicode_user
6163
64
62class SummitManager(CurrentSiteManager):65class SummitManager(CurrentSiteManager):
6366
64 def next(self):67 def next(self):
@@ -68,6 +71,7 @@
68 # No summits have been defined in the database yet71 # No summits have been defined in the database yet
69 return Summit(name="no_summits", title="No Summits Defined")72 return Summit(name="no_summits", title="No Summits Defined")
7073
74
71class Summit(models.Model):75class Summit(models.Model):
72 STATE_CHOICES = (76 STATE_CHOICES = (
73 (u'sponsor', u'Sponsorship Requests'),77 (u'sponsor', u'Sponsorship Requests'),
@@ -81,22 +85,51 @@
81 sites = models.ManyToManyField(Site)85 sites = models.ManyToManyField(Site)
82 location = models.CharField(max_length=100, blank=True)86 location = models.CharField(max_length=100, blank=True)
83 description = models.TextField(max_length=2047, blank=True)87 description = models.TextField(max_length=2047, blank=True)
84 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")88 etherpad = models.URLField(
85 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")89 verify_exists=False,
90 max_length=75,
91 blank=False,
92 default='http://pad.ubuntu.com/',
93 help_text="Enter the URL of the etherpad server you would like to use"
94 )
95 qr = models.URLField(
96 verify_exists=False,
97 max_length=100,
98 blank=True,
99 default='',
100 help_text="Enter the URL of the QR code for mobile device application"
101 )
86 hashtag = models.CharField(max_length=25, blank=True)102 hashtag = models.CharField(max_length=25, blank=True)
87 timezone = models.CharField(max_length=50,103 timezone = models.CharField(
88 choices=[(x, x) for x in pytz.common_timezones])104 max_length=50,
105 choices=[(x, x) for x in pytz.common_timezones]
106 )
89 last_update = models.DateTimeField(null=True, blank=True)107 last_update = models.DateTimeField(null=True, blank=True)
90 state = models.CharField(max_length=10, choices=STATE_CHOICES,108 state = models.CharField(
91 default=STATE_CHOICES[0][0])109 max_length=10,
110 choices=STATE_CHOICES,
111 default=STATE_CHOICES[0][0]
112 )
92 date_start = models.DateField(blank=False, null=True)113 date_start = models.DateField(blank=False, null=True)
93 date_end = models.DateField(blank=False, null=True)114 date_end = models.DateField(blank=False, null=True)
94 managers = models.ManyToManyField(User, blank=True, related_name='managers')115 managers = models.ManyToManyField(
95 schedulers = models.ManyToManyField(User, blank=True, related_name='schedulers')116 User,
117 blank=True,
118 related_name='managers'
119 )
120 schedulers = models.ManyToManyField(
121 User,
122 blank=True,
123 related_name='schedulers'
124 )
96 virtual_summit = models.BooleanField(125 virtual_summit = models.BooleanField(
97 help_text="Check this if the entire sprint is virtual"126 help_text="Check this if the entire sprint is virtual"
98 )127 )
99 help_text = models.TextField(null=True, blank=True, help_text='Summit specific instructions and links for getting help during the event')128 help_text = models.TextField(
129 null=True,
130 blank=True,
131 help_text='Instructions and links for getting help during the event'
132 )
100133
101 objects = models.Manager()134 objects = models.Manager()
102 on_site = SummitManager()135 on_site = SummitManager()
@@ -109,7 +142,14 @@
109 return self.name142 return self.name
110143
111 def get_absolute_url(self):144 def get_absolute_url(self):
112 return getattr(settings, 'SITE_ROOT', 'http://summit.ubuntu.com') + reverse('summit.schedule.views.summit', args=(self.name,))145 return getattr(
146 settings,
147 'SITE_ROOT',
148 'http://summit.ubuntu.com'
149 ) + reverse(
150 'summit.schedule.views.summit',
151 args=(self.name,)
152 )
113153
114 def localize(self, datetime):154 def localize(self, datetime):
115 """Convert a datetime to the summit-local timezone.155 """Convert a datetime to the summit-local timezone.
@@ -172,7 +212,14 @@
172 return sorted(dates)212 return sorted(dates)
173213
174 def ical_url(self):214 def ical_url(self):
175 return getattr(settings, 'SITE_ROOT', 'http://summit.ubuntu.com') + reverse('summit.schedule.views.ical', args=(self.name,))215 return getattr(
216 settings,
217 'SITE_ROOT',
218 'http://summit.ubuntu.com'
219 ) + reverse(
220 'summit.schedule.views.ical',
221 args=(self.name,)
222 )
176223
177 def public_rooms(self):224 def public_rooms(self):
178 """List of public rooms for this summit.225 """List of public rooms for this summit.
@@ -192,7 +239,9 @@
192 else:239 else:
193 return cmp(a.track.title, b.track.title)240 return cmp(a.track.title, b.track.title)
194241
195 rooms = self.room_set.exclude(Q(type__exact='closed') | Q(type__exact='private'))242 rooms = self.room_set.exclude(
243 Q(type__exact='closed') | Q(type__exact='private')
244 )
196 return sorted(rooms, cmp=by_title)245 return sorted(rooms, cmp=by_title)
197246
198 def open_rooms(self):247 def open_rooms(self):
@@ -231,8 +280,12 @@
231 if sprints.count() > 0:280 if sprints.count() > 0:
232 urls = [sprint.import_url for sprint in sprints]281 urls = [sprint.import_url for sprint in sprints]
233 else:282 else:
234 urls = [("https://launchpad.net/sprints/%s/+temp-meeting-export"283 urls = [
235 % self.name)]284 (
285 "https://launchpad.net/sprints/%s/+temp-meeting-export"
286 % self.name
287 )
288 ]
236 return urls289 return urls
237290
238 def update_from_launchpad_response(self, response, options={}):291 def update_from_launchpad_response(self, response, options={}):
@@ -253,9 +306,16 @@
253 while trycounter <= retrytotal:306 while trycounter <= retrytotal:
254 req = urllib2.Request(url)307 req = urllib2.Request(url)
255 req.add_header("Cache-Control", "no-cache")308 req.add_header("Cache-Control", "no-cache")
256 req.add_header("Cookie", "lp=%s" % getattr(settings, "LP_AUTH_COOKIE", "please-don't-cache-me"))309 req.add_header(
310 "Cookie",
311 "lp=%s" % getattr(
312 settings,
313 "LP_AUTH_COOKIE",
314 "please-don't-cache-me"
315 )
316 )
257 try:317 try:
258 export = urllib2.urlopen(req)318 export = urllib2.urlopen(req)
259 except urllib2.HTTPError, e:319 except urllib2.HTTPError, e:
260 trycounter += 1320 trycounter += 1
261 if trycounter >= retrytotal:321 if trycounter >= retrytotal:
@@ -278,12 +338,16 @@
278 in_lp |= self.update_from_launchpad_response(sprint_info, options)338 in_lp |= self.update_from_launchpad_response(sprint_info, options)
279339
280 if not options.get('skip_meetings', False):340 if not options.get('skip_meetings', False):
281 in_db = set(m for m in self.meeting_set.exclude(launchpad_blueprint_id__isnull=True))341 in_db = set(
342 m for m in self.meeting_set.exclude(
343 launchpad_blueprint_id__isnull=True
344 )
345 )
282346
283 for extra in in_db.difference(in_lp):347 for extra in in_db.difference(in_lp):
284 print "Marking %s as removed" % extra.name348 print "Marking %s as removed" % extra.name
285 extra.agenda_set.all().delete()349 extra.agenda_set.all().delete()
286 extra.approved='REMOVED'350 extra.approved = 'REMOVED'
287 extra.save()351 extra.save()
288352
289 self.last_update = datetime.utcnow()353 self.last_update = datetime.utcnow()
@@ -298,19 +362,26 @@
298362
299 print "user %s" % username363 print "user %s" % username
300 try:364 try:
301 attendee = self.attendee_set.get(user__username__exact=username[:30])365 attendee = self.attendee_set.get(
366 user__username__exact=username[:30]
367 )
302 except ObjectDoesNotExist:368 except ObjectDoesNotExist:
303 try:369 try:
304 user = User.objects.get(username__exact=username[:30])370 user = User.objects.get(username__exact=username[:30])
305 except ObjectDoesNotExist:371 except ObjectDoesNotExist:
306 user = User.objects.create_user(username[:30], '', password=None)372 user = User.objects.create_user(
373 username[:30],
374 '',
375 password=None
376 )
307 launchpad.set_user_openid(user)377 launchpad.set_user_openid(user)
308378
309 # Create with any start/end time since we overwrite shortly379 # Create with any start/end time since we overwrite shortly
310 attendee = self.attendee_set.create(user=user,380 attendee = self.attendee_set.create(
311 start=datetime.utcnow(),381 user=user,
312 end=datetime.utcnow())382 start=datetime.utcnow(),
313383 end=datetime.utcnow()
384 )
314385
315 attendee.update_from_launchpad(elem)386 attendee.update_from_launchpad(elem)
316387
@@ -333,7 +404,12 @@
333 try:404 try:
334 meeting = self.meeting_set.get(launchpad_blueprint_id=bp_id)405 meeting = self.meeting_set.get(launchpad_blueprint_id=bp_id)
335 except ObjectDoesNotExist:406 except ObjectDoesNotExist:
336 meeting = self.meeting_set.create(name=name, title=full_name[:100], slots=slot_length, launchpad_blueprint_id=bp_id)407 meeting = self.meeting_set.create(
408 name=name,
409 title=full_name[:100],
410 slots=slot_length,
411 launchpad_blueprint_id=bp_id
412 )
337 except:413 except:
338 pass414 pass
339415
@@ -347,13 +423,18 @@
347 This is a pretty simple best-fit/first-come-first-served scheduler,423 This is a pretty simple best-fit/first-come-first-served scheduler,
348 but it suffices.424 but it suffices.
349 """425 """
350 for meeting in self.meeting_set.filter(approved='APPROVED', agenda__isnull=True).order_by('id'):426 for meeting in self.meeting_set.filter(
351 meeting.try_schedule(with_interested = True)427 approved='APPROVED',
428 agenda__isnull=True
429 ).order_by('id'):
430 meeting.try_schedule(with_interested=True)
352431
353 for meeting in self.meeting_set.filter(approved='APPROVED', agenda__isnull=True).order_by('id'):432 for meeting in self.meeting_set.filter(
433 approved='APPROVED',
434 agenda__isnull=True
435 ).order_by('id'):
354 meeting.try_schedule()436 meeting.try_schedule()
355437
356
357 def check_schedule(self):438 def check_schedule(self):
358 """Check the schedule for existant errors."""439 """Check the schedule for existant errors."""
359 for meeting in self.meeting_set.all():440 for meeting in self.meeting_set.all():
@@ -361,14 +442,20 @@
361 try:442 try:
362 missing = meeting.check_schedule(agenda.slot, agenda.room)443 missing = meeting.check_schedule(agenda.slot, agenda.room)
363 if len(missing):444 if len(missing):
364 print "Warning: required people not available: %s at %s in %s: %s" % (445 print "Warning: required people not available:"
365 meeting, agenda.slot, agenda.room,446 "%s at %s in %s: %s" % (
366 ', '.join(m.user.username for m in missing))447 meeting,
448 agenda.slot,
449 agenda.room,
450 ', '.join(m.user.username for m in missing)
451 )
367 except meeting.SchedulingError, e:452 except meeting.SchedulingError, e:
368 print "Error: %s at %s in %s: %s" % (meeting,453 print "Error: %s at %s in %s: %s" % (
369 agenda.slot,454 meeting,
370 agenda.room,455 agenda.slot,
371 e)456 agenda.room,
457 e
458 )
372459
373 def reschedule(self):460 def reschedule(self):
374 """Delete any automatically created agenda items that have problems."""461 """Delete any automatically created agenda items that have problems."""
@@ -426,6 +513,7 @@
426 return self.lead_set.filter(lead=attendee).exists()513 return self.lead_set.filter(lead=attendee).exists()
427 return False514 return False
428515
516
429class SummitSprint(models.Model):517class SummitSprint(models.Model):
430518
431 summit = models.ForeignKey(Summit, related_name='sprint_set')519 summit = models.ForeignKey(Summit, related_name='sprint_set')
432520
=== added file 'summit/schedule/templates/schedule/edit_hangout.html'
--- summit/schedule/templates/schedule/edit_hangout.html 1970-01-01 00:00:00 +0000
+++ summit/schedule/templates/schedule/edit_hangout.html 2013-02-22 01:25:24 +0000
@@ -0,0 +1,45 @@
1{% extends "base.html" %}
2
3{% block page_name %}Edit Hangout - {{ summit.title }}{%endblock %}
4{% block sub_nav %}{% endblock %}
5
6{% block extrahead %}{{ block.super }}
7 <script type="text/javascript" src="{{MEDIA_URL}}js/colortip-1.0-jquery.js"></script>
8 <link rel="stylesheet" type="text/css" href="{{MEDIA_URL}}css/colortip-1.0-jquery.css"/>
9{% endblock %}
10
11{% block closure %}
12<script type="text/javascript"><!--
13$(document).ready(function(){
14 $('span[rel*=help]').colorTip({color:'orange'});
15});
16--></script>
17<style>
18form ul {
19 height: 12em;
20 overflow-y: scroll;
21 overflow-x: hidden;
22}
23</style>
24{% endblock %}
25
26
27{% block content %}
28<div class="row">
29 <article id="form" class="span-8">
30 {% if form.errors %}
31 <p style="color: red;">
32 Please correct the error{{ form.errors|pluralize }} below.
33 </p>
34 {% endif %}
35
36 <form action="{{ request.path_info }}" method="POST">
37 <fieldset>
38 <h3>Edit Hangout</h3>
39 {{ form.as_template }}
40 {% if is_popup %}<input type="hidden" name="_popup" value="1">{% endif %}
41 <input type="submit" name="submit" value="Save" class="submit-button" />
42 </fieldset>
43 </form>
44 </article>
45{% endblock %}
046
=== added file 'summit/schedule/templates/schedule/virtual_meeting.html'
--- summit/schedule/templates/schedule/virtual_meeting.html 1970-01-01 00:00:00 +0000
+++ summit/schedule/templates/schedule/virtual_meeting.html 2013-02-22 01:25:24 +0000
@@ -0,0 +1,146 @@
1{% extends "base.html" %}
2{% load schedule_perms datetime markup %}
3
4{% block page_name %}
5 {{ meeting.title }} -
6 {% if schedule.date %}{{ schedule.date|strftime:"%Y-%m-%d" }}{% endif %}
7 {% if schedule.room %}{{ schedule.room.title }} - {{ summit.title }}{% endif %}
8{% endblock %}
9
10{% block extrahead %}{{ block.super }}
11 <link rel="stylesheet" type="text/css" media="screen" href="/media/css/virt.css" />
12<meta property="fb:app_id" content="310260202349342" />
13<meta property="og:title" content="{{ meeting.title }}{% if schedule.date %} - {{ schedule.date|strftime:"%Y-%m-%d" }}{% endif %}{% if schedule.room %}{{ schedule.room.title }}{% endif %}" />
14{% if meeting.description %}
15<meta property="og:description" content="{{ meeting.description|linebreaks|striptags }}" />
16{% endif %}
17<meta property="og:url" content="http://summit.ubuntu.com{% url summit.schedule.views.meeting meeting.summit.name, meeting.id, meeting.name|default:'-' %}" />
18<meta property="og:image" content="http://summit.ubuntu.com/media/images/cof_orange_hex1.png" />
19<meta property="og:site_name" content="The Summit Scheduler" />
20<meta property="og:type" content="article" />
21<meta itemprop="name" content="{{ meeting.title }}{% if schedule.date %} - {{ schedule.date|strftime:"%Y-%m-%d" }}{% endif %}{% if schedule.room %}{{ schedule.room.title }}{% endif %}" />
22<meta itemprop="description" content="{{ meeting.description|linebreaks|striptags }}" />
23{% endblock %}
24
25{% block sub_nav_links %}
26 {% if meeting.private %}
27 {% if meeting.private_key and meeting.private_key != '' %}
28 <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>
29 {% else %}
30 <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>
31 {% endif %}
32 {% endif %}
33
34 {% if meeting.spec_url %}
35 {% if summit_organizer or drafter %}
36 <li><a class="sub-nav-item" href="{% url summit.schedule.views.attendee_review summit.name, meeting.id, meeting.name|default:'-' %}">Review attendees</a></li>
37 <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>
38 {% endif %}
39 <li><a class="sub-nav-item" href="{{ meeting.spec_url }}">Blueprint</a></li>
40 {% else %}
41 {% if summit_organizer or drafter %}
42 {% if not drafter %}
43 <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>
44 {% endif %}
45 {% if not summit_organizer %}
46 <li><a class="sub-nav-item" href="{% url summit.schedule.views.edit_meeting summit.name, meeting.id, meeting.name|default:'-' %}">Edit meeting</a></li>
47 {% endif %}
48 <li><a class="sub-nav-item" href="{% url summit.schedule.views.attendee_review summit.name, meeting.id, meeting.name|default:'-' %}">Review attendees</a></li>
49 <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>
50 {% endif %}
51 {% endif %}
52
53 {% if user_is_attending %}
54 {% if user_is_participating %}
55 <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>
56 {% endif %}
57 {% else %}
58 {% if meeting.spec_url %}
59 <li><a class="sub-nav-item" href="{{ meeting.spec_url }}/+subscribe">Subscribe to blueprint</a></li>
60 {% endif %}
61 <li><a class="sub-nav-item" href="{% url summit.schedule.views.attend_meeting meeting.summit.name, meeting.id %}">Attend this meeting</a></li>
62 {% endif %}
63
64 {% if scheduler %}
65 <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>
66 {% endif %}
67{% endblock %}
68
69{% block content %}
70<div class="row">
71<section class="span-9">
72 <h2>{{ meeting.title }}</h2>
73 <div id="description">
74 {{ meeting.description|markdown:'safe' }}
75 <h3><a href="{{ meeting.hangout_url }}">Join the Hangout on Air</a></h3>
76 </div>
77
78</section>
79<article class="span-3 last">
80{% if meeting.private %}
81{% else %}
82<div class="share">
83 <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 />
84 <div id="fb-root"></div>
85 <script>(function(d, s, id) {
86 var js, fjs = d.getElementsByTagName(s)[0];
87 if (d.getElementById(id)) {return;}
88 js = d.createElement(s); js.id = id;
89 js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=310260202349342";
90 fjs.parentNode.insertBefore(js, fjs);
91 }(document, 'script', 'facebook-jssdk'));</script>
92 <div class="fb-like" data-href="" data-send="false" data-layout="box_count" data-width="40" data-show-faces="false" data-font="arial"></div>
93 <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
94 <g:plusone size="tall"></g:plusone>
95 <a href="http://twitter.com/share" class="twitter-share-button" data-count="vertical" data-lang="en">Tweet</a>
96 <script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
97 <script src="http://www.stumbleupon.com/hostedbadge.php?s=5"></script>
98</div>
99
100{% endif %}
101</article>
102</div>
103<div class="row">
104 <div class="span-4">
105 <div align="center"><iframe width="420" height="295" src="{{ meeting.broadcast_url }}" frameborder="0" allowfullscreen></iframe></div>
106 <iframe src="http://webchat.freenode.net?channels={% for ai in agenda_items %}{{ ai.room.irc_channel }}{% endfor %}&uio=Mj10cnVlJjQ9dHJ1ZSY5PXRydWUmMTA9dHJ1ZSYxMz1mYWxzZSYxND1mYWxzZQbf" width="100%" height="395"></iframe>
107</div>
108<div class="span-7 last">
109 {% if meeting.private %}
110 <h3>WARNING: Contents of this pad may not be private, and may be searcheable by non-attendees!</h3>
111 {% endif %}
112
113<iframe width=100% height=700 src="{{ meeting.link_to_pad }}"></iframe>
114</div>
115</div>
116<div class="row">
117 {% ifnotequal meeting.type 'plenary' %}
118 <div id="Attendees" class="span-4">
119 <h3>Attendees</h3>
120 {% for attendee in attendees %}
121 <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 %}
122 {% endfor %}
123 </div>
124 {% endifnotequal %}
125 <div class="span-3">
126{% if summit_organizer %}
127 {% include "schedule/admin.html" %}
128{% endif %}
129 </div>
130 <div id="Links" class="span-3 last">
131 <h3>Links</h3>
132 <ul>
133 <li><a href="{{meeting.link_to_pad}}" target="_new">Notes in a separate window</a></li>
134 <li><a href="{{meeting.edit_link_to_pad}}" target="_new">Edit notes window</a></li>
135 {% if meeting.spec_url %}<li><a href="{{ meeting.spec_url }}">Blueprint</a></li>{% endif %}
136 {% if meeting.wiki_url %}<li><a href="{{ meeting.wiki_url }}">Wiki page</a></li>{% endif %}
137 {% for ai in agenda_items %}
138 {% 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 %}
139 {% endfor %}
140
141 </ul>
142 </div>
143
144</article>
145</div>
146{% endblock %}
0147
=== added directory 'summit/schedule/tests'
=== added file 'summit/schedule/tests/__init__.py'
--- summit/schedule/tests/__init__.py 1970-01-01 00:00:00 +0000
+++ summit/schedule/tests/__init__.py 2013-02-22 01:25:24 +0000
@@ -0,0 +1,17 @@
1# The Summit Scheduler web application
2# Copyright (C) 2008 - 2012 Ubuntu Community, Canonical Ltd
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as
6# published by the Free Software Foundation, either version 3 of the
7# License, or (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17from tests import *
018
=== renamed file 'summit/schedule/tests.py' => 'summit/schedule/tests/tests.py'
=== modified file 'summit/schedule/views.py'
--- summit/schedule/views.py 2012-10-26 10:23:28 +0000
+++ summit/schedule/views.py 2013-02-22 01:25:24 +0000
@@ -49,7 +49,8 @@
49 EditMeeting,49 EditMeeting,
50 MeetingReview,50 MeetingReview,
51 AttendMeeting,51 AttendMeeting,
52 OrganizerChangeAttend52 OrganizerChangeAttend,
53 EditMeetingHangout
53)54)
5455
55__all__ = (56__all__ = (
@@ -60,6 +61,7 @@
60 'today_view',61 'today_view',
61)62)
6263
64
63@summit_required65@summit_required
64def summit(request, summit, attendee):66def summit(request, summit, attendee):
65 edit = False67 edit = False
@@ -81,14 +83,17 @@
81 return render_to_response("schedule/summit.html", context,83 return render_to_response("schedule/summit.html", context,
82 context_instance=RequestContext(request))84 context_instance=RequestContext(request))
8385
86
84@summit_only_required87@summit_only_required
85def search(request, summit):88def search(request, summit):
86 query = request.GET.get('q', None)89 query = request.GET.get('q', None)
87 if query:90 if query:
88 meetings = summit.meeting_set.filter(Q(name__icontains=query) | Q(title__icontains=query))91 meetings = summit.meeting_set.filter(
92 Q(name__icontains=query) | Q(title__icontains=query)
93 )
89 else:94 else:
90 meetings = []95 meetings = []
91 96
92 context = {97 context = {
93 'summit': summit,98 'summit': summit,
94 'query': query,99 'query': query,
@@ -96,17 +101,28 @@
96 }101 }
97 return render_to_response("schedule/search.html", context,102 return render_to_response("schedule/search.html", context,
98 context_instance=RequestContext(request))103 context_instance=RequestContext(request))
104
105
99@summit_required106@summit_required
100def daily_schedule(request, summit, attendee, date):107def daily_schedule(request, summit, attendee, date):
101 viewdate = summit.as_localtime(datetime.datetime.strptime(date, "%Y-%m-%d"))108 viewdate = summit.as_localtime(
109 datetime.datetime.strptime(date, "%Y-%m-%d")
110 )
102 utc_date = summit.delocalize(viewdate)111 utc_date = summit.delocalize(viewdate)
103 day = datetime.timedelta(days=1)112 day = datetime.timedelta(days=1)
104113
105 schedule = SortedDict()114 schedule = SortedDict()
106 multislot_meetings = SortedDict()115 multislot_meetings = SortedDict()
107116
108 for slot in summit.slot_set.filter(start_utc__gte=utc_date, end_utc__lte=(utc_date+day)).order_by('start_utc'):117 for slot in summit.slot_set.filter(
109 if not (slot.type == 'open' or slot.type == 'plenary' or slot.type == 'lunch'):118 start_utc__gte=utc_date,
119 end_utc__lte=(utc_date+day)
120 ).order_by('start_utc'):
121 if not (
122 slot.type == 'open' or
123 slot.type == 'plenary' or
124 slot.type == 'lunch'
125 ):
110 continue126 continue
111 if not slot in schedule:127 if not slot in schedule:
112 schedule[slot] = SortedDict()128 schedule[slot] = SortedDict()
@@ -117,7 +133,7 @@
117 if count == 1:133 if count == 1:
118 del multislot_meetings[agenda]134 del multislot_meetings[agenda]
119 else:135 else:
120 multislot_meetings[agenda] = count -1136 multislot_meetings[agenda] = count - 1
121137
122 # Add meetings from this slot138 # Add meetings from this slot
123 for agenda in slot.agenda_set.select_related().order_by('room__name'):139 for agenda in slot.agenda_set.select_related().order_by('room__name'):
@@ -125,7 +141,7 @@
125 schedule[slot][agenda.room] = agenda141 schedule[slot][agenda.room] = agenda
126 if agenda.meeting.slots > 1:142 if agenda.meeting.slots > 1:
127 multislot_meetings[agenda] = agenda.meeting.slots - 1143 multislot_meetings[agenda] = agenda.meeting.slots - 1
128 144
129 if '_popup' in request.GET:145 if '_popup' in request.GET:
130 is_popup = True146 is_popup = True
131147
@@ -141,29 +157,49 @@
141 }157 }
142 return render_to_response("schedule/daily.html", context,158 return render_to_response("schedule/daily.html", context,
143 context_instance=RequestContext(request))159 context_instance=RequestContext(request))
144 160
161
145@summit_attendee_required162@summit_attendee_required
146def attendee_schedule(request, summit, attendee):163def attendee_schedule(request, summit, attendee):
147 pass164 pass
148 165
166
149@summit_required167@summit_required
150def by_date(request, summit, attendee, date):168def by_date(request, summit, attendee, date):
151 return _process_date_view(request, summit, attendee, date)169 return _process_date_view(request, summit, attendee, date)
152170
171
153@summit_required172@summit_required
154def today_view(request, summit, attendee):173def today_view(request, summit, attendee):
155 today = summit.localize(datetime.datetime.now()).date()174 today = summit.localize(datetime.datetime.now()).date()
156 return _process_date_view(request, summit, attendee, today.strftime("%Y-%m-%d"))175 return _process_date_view(
176 request,
177 summit,
178 attendee,
179 today.strftime("%Y-%m-%d")
180 )
181
157182
158def _process_date_view(request, summit, attendee, date):183def _process_date_view(request, summit, attendee, date):
159 if 'rooms' in request.GET:184 if 'rooms' in request.GET:
160 roomnames = request.GET.get('rooms', '').split(',')185 roomnames = request.GET.get('rooms', '').split(',')
161 rooms = list(summit.room_set.filter(name__in=roomnames, type='open'))186 rooms = list(summit.room_set.filter(name__in=roomnames, type='open'))
162 if request.user.is_authenticated() and request.user.is_staff:187 if request.user.is_authenticated() and request.user.is_staff:
163 rooms += list(summit.room_set.filter(name__in=roomnames, type='private'))188 rooms += list(
189 summit.room_set.filter(
190 name__in=roomnames,
191 type='private'
192 )
193 )
164 else:194 else:
165 rooms = None195 rooms = None
166 schedule = schedule_factory(request, summit, attendee, room=rooms, date=date)196 schedule = schedule_factory(
197 request,
198 summit,
199 attendee,
200 room=rooms,
201 date=date
202 )
167203
168 if request.method == 'POST':204 if request.method == 'POST':
169 return schedule.save_change()205 return schedule.save_change()
@@ -183,25 +219,42 @@
183 'previousday': viewdate - day,219 'previousday': viewdate - day,
184 'can_change_agenda': summit.can_change_agenda(attendee),220 'can_change_agenda': summit.can_change_agenda(attendee),
185 }221 }
186 converted_date = summit.delocalize(datetime.datetime.strptime(date, "%Y-%m-%d"))222 converted_date = summit.delocalize(
187 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:223 datetime.datetime.strptime(date, "%Y-%m-%d")
224 )
225 if 'edit' in request.GET or Slot.objects.filter(
226 summit=summit,
227 start_utc__gte=converted_date,
228 end_utc__lte=converted_date+datetime.timedelta(days=1)
229 ).count() > 0:
188 schedule.calculate()230 schedule.calculate()
189 else:231 else:
190 return render_to_response("schedule/nosession.html", context,232 return render_to_response("schedule/nosession.html", context,
191 context_instance=RequestContext(request))233 context_instance=RequestContext(request))
192 return render_to_response("schedule/schedule.html", context,234 return render_to_response("schedule/schedule.html", context,
193 context_instance=RequestContext(request))235 context_instance=RequestContext(request))
194236
237
195@summit_required238@summit_required
196def next_table(request, summit, attendee):239def next_table(request, summit, attendee):
197 if 'rooms' in request.GET:240 if 'rooms' in request.GET:
198 roomnames = request.GET.get('rooms', '').split(',')241 roomnames = request.GET.get('rooms', '').split(',')
199 rooms = list(summit.room_set.filter(name__in=roomnames, type='open'))242 rooms = list(summit.room_set.filter(name__in=roomnames, type='open'))
200 if request.user.is_authenticated() and request.user.is_staff:243 if request.user.is_authenticated() and request.user.is_staff:
201 rooms += list(summit.room_set.filter(name__in=roomnames, type='private'))244 rooms += list(
245 summit.room_set.filter(
246 name__in=roomnames, type='private'
247 )
248 )
202 else:249 else:
203 rooms = None250 rooms = None
204 schedule = Schedule.from_request(request, summit, attendee, room=rooms, nextonly=True)251 schedule = Schedule.from_request(
252 request,
253 summit,
254 attendee,
255 room=rooms,
256 nextonly=True
257 )
205258
206 schedule.calculate()259 schedule.calculate()
207260
@@ -214,6 +267,7 @@
214 return render_to_response("schedule/nextsession_table.html", context,267 return render_to_response("schedule/nextsession_table.html", context,
215 context_instance=RequestContext(request))268 context_instance=RequestContext(request))
216269
270
217@summit_required271@summit_required
218def next_session(request, summit, attendee):272def next_session(request, summit, attendee):
219 url_content = request.GET.urlencode(safe='_:')273 url_content = request.GET.urlencode(safe='_:')
@@ -226,16 +280,21 @@
226 return render_to_response("schedule/nextsession.html", context,280 return render_to_response("schedule/nextsession.html", context,
227 context_instance=RequestContext(request))281 context_instance=RequestContext(request))
228282
283
229@summit_required284@summit_required
230def by_room(request, summit, attendee, room_name):285def by_room(request, summit, attendee, room_name):
231 schedule = SortedDict()286 schedule = SortedDict()
232 multislot_meetings = SortedDict()287 multislot_meetings = SortedDict()
233288
234 room = get_object_or_404(Room, name=room_name, summit=summit)289 room = get_object_or_404(Room, name=room_name, summit=summit)
235 290
236 for slot in summit.slot_set.all().order_by('start_utc'):291 for slot in summit.slot_set.all().order_by('start_utc'):
237292
238 if not (slot.type == 'open' or slot.type == 'plenary' or slot.type == 'lunch'):293 if not (
294 slot.type == 'open' or
295 slot.type == 'plenary' or
296 slot.type == 'lunch'
297 ):
239 continue298 continue
240 if not slot in schedule:299 if not slot in schedule:
241 schedule[slot] = SortedDict()300 schedule[slot] = SortedDict()
@@ -246,7 +305,7 @@
246 if count == 1:305 if count == 1:
247 del multislot_meetings[agenda]306 del multislot_meetings[agenda]
248 else:307 else:
249 multislot_meetings[agenda] = count -1308 multislot_meetings[agenda] = count - 1
250309
251 # Add meetings from this slot310 # Add meetings from this slot
252 for agenda in slot.agenda_set.filter(room=room).select_related():311 for agenda in slot.agenda_set.filter(room=room).select_related():
@@ -277,7 +336,11 @@
277336
278 for slot in summit.slot_set.all().order_by('start_utc'):337 for slot in summit.slot_set.all().order_by('start_utc'):
279338
280 if not (slot.type == 'open' or slot.type == 'plenary' or slot.type == 'lunch'):339 if not (
340 slot.type == 'open' or
341 slot.type == 'plenary' or
342 slot.type == 'lunch'
343 ):
281 continue344 continue
282 if not slot in schedule:345 if not slot in schedule:
283 schedule[slot] = SortedDict()346 schedule[slot] = SortedDict()
@@ -288,10 +351,12 @@
288 if count == 1:351 if count == 1:
289 del multislot_meetings[agenda]352 del multislot_meetings[agenda]
290 else:353 else:
291 multislot_meetings[agenda] = count -1354 multislot_meetings[agenda] = count - 1
292355
293 # Add meetings from this slot356 # Add meetings from this slot
294 for agenda in slot.agenda_set.filter(meeting__tracks=track).select_related().order_by('room__name'):357 for agenda in slot.agenda_set.filter(
358 meeting__tracks=track
359 ).select_related().order_by('room__name'):
295 if not agenda.meeting.private or attendee in agenda.meeting.attendees:360 if not agenda.meeting.private or attendee in agenda.meeting.attendees:
296 schedule[slot][agenda.room] = agenda361 schedule[slot][agenda.room] = agenda
297 if agenda.meeting.slots > 1:362 if agenda.meeting.slots > 1:
@@ -309,16 +374,25 @@
309 return render_to_response("schedule/by_track.html", context,374 return render_to_response("schedule/by_track.html", context,
310 context_instance=RequestContext(request))375 context_instance=RequestContext(request))
311376
377
312@summit_required378@summit_required
313def by_participant(request, summit, attendee, username):379def by_participant(request, summit, attendee, username):
314 schedule = SortedDict()380 schedule = SortedDict()
315 multislot_meetings = SortedDict()381 multislot_meetings = SortedDict()
316382
317 participant = get_object_or_404(Attendee, user__username=username, summit=summit)383 participant = get_object_or_404(
384 Attendee,
385 user__username=username,
386 summit=summit
387 )
318388
319 for slot in summit.slot_set.all().order_by('start_utc'):389 for slot in summit.slot_set.all().order_by('start_utc'):
320390
321 if not (slot.type == 'open' or slot.type == 'plenary' or slot.type == 'lunch'):391 if not (
392 slot.type == 'open' or
393 slot.type == 'plenary' or
394 slot.type == 'lunch'
395 ):
322 continue396 continue
323 if not slot in schedule:397 if not slot in schedule:
324 schedule[slot] = SortedDict()398 schedule[slot] = SortedDict()
@@ -329,10 +403,18 @@
329 if count == 1:403 if count == 1:
330 del multislot_meetings[agenda]404 del multislot_meetings[agenda]
331 else:405 else:
332 multislot_meetings[agenda] = count -1406 multislot_meetings[agenda] = count - 1
333407
334 # Add meetings from this slot408 # Add meetings from this slot
335 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'):409 for agenda in slot.agenda_set.filter(
410 Q(
411 meeting__participant__attendee=participant
412 ) | Q(
413 meeting__drafter=participant
414 ) | Q(
415 meeting__assignee=participant
416 )
417 ).select_related().order_by('room__name'):
336 if not agenda.meeting.private or attendee in agenda.meeting.attendees:418 if not agenda.meeting.private or attendee in agenda.meeting.attendees:
337 schedule[slot][agenda.room] = agenda419 schedule[slot][agenda.room] = agenda
338 if agenda.meeting.slots > 1:420 if agenda.meeting.slots > 1:
@@ -350,6 +432,7 @@
350 return render_to_response("schedule/by_participant.html", context,432 return render_to_response("schedule/by_participant.html", context,
351 context_instance=RequestContext(request))433 context_instance=RequestContext(request))
352434
435
353@summit_only_required436@summit_only_required
354def tracks(request, summit):437def tracks(request, summit):
355438
@@ -359,6 +442,7 @@
359 return render_to_response("schedule/tracks.html", context,442 return render_to_response("schedule/tracks.html", context,
360 context_instance=RequestContext(request))443 context_instance=RequestContext(request))
361444
445
362@summit_required446@summit_required
363def meeting(request, summit, attendee, meeting_id, meeting_slug):447def meeting(request, summit, attendee, meeting_id, meeting_slug):
364 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)448 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
@@ -366,11 +450,13 @@
366 raise Http404450 raise Http404
367 return _show_meeting(request, summit, meeting, attendee)451 return _show_meeting(request, summit, meeting, attendee)
368452
453
369@summit_required454@summit_required
370def private_meeting(request, summit, attendee, private_key, meeting_slug):455def private_meeting(request, summit, attendee, private_key, meeting_slug):
371 meeting = get_object_or_404(summit.meeting_set, private_key=private_key)456 meeting = get_object_or_404(summit.meeting_set, private_key=private_key)
372 return _show_meeting(request, summit, meeting, attendee)457 return _show_meeting(request, summit, meeting, attendee)
373458
459
374def _show_meeting(request, summit, meeting, attendee):460def _show_meeting(request, summit, meeting, attendee):
375 agendaitems = meeting.agenda_set.all()461 agendaitems = meeting.agenda_set.all()
376 participants = meeting.participant_set.all()462 participants = meeting.participant_set.all()
@@ -378,29 +464,40 @@
378 tracks = meeting.tracks.all()464 tracks = meeting.tracks.all()
379 user_is_attending = attendee is not None and attendee in meeting.attendees465 user_is_attending = attendee is not None and attendee in meeting.attendees
380 user_is_participating = attendee is not None and attendee in [p.attendee for p in participants if not p.from_launchpad]466 user_is_participating = attendee is not None and attendee in [p.attendee for p in participants if not p.from_launchpad]
381 467
382 if attendee == meeting.drafter:468 if attendee == meeting.drafter:
383 drafter = True469 drafter = True
384 else:470 else:
385 drafter = False471 drafter = False
386 472
387 context = {473 context = {
388 'summit': summit,474 'summit': summit,
389 'meeting':meeting,475 'meeting': meeting,
390 'agenda_items':agendaitems,476 'agenda_items': agendaitems,
391 'participants':participants,477 'participants': participants,
392 'attendees': attendees,478 'attendees': attendees,
393 'user_is_attending': user_is_attending,479 'user_is_attending': user_is_attending,
394 'user_is_participating': user_is_participating,480 'user_is_participating': user_is_participating,
395 'tracks':tracks,481 'tracks': tracks,
396 'ETHERPAD_HOST': summit.etherpad,482 'ETHERPAD_HOST': summit.etherpad,
397 'summit_organizer': summit.is_organizer(attendee),483 'summit_organizer': summit.is_organizer(attendee),
398 'scheduler': summit.can_change_agenda(attendee),484 'scheduler': summit.can_change_agenda(attendee),
399 'is_scheduler': summit.is_scheduler(attendee),485 'is_scheduler': summit.is_scheduler(attendee),
400 'drafter': drafter,486 'drafter': drafter,
401 }487 }
402 return render_to_response("schedule/meeting.html", context,488 if summit.virtual_summit or meeting.virtual_meeting:
403 context_instance=RequestContext(request))489 return render_to_response(
490 "schedule/virtual_meeting.html",
491 context,
492 context_instance=RequestContext(request)
493 )
494 else:
495 return render_to_response(
496 "schedule/meeting.html",
497 context,
498 context_instance=RequestContext(request)
499 )
500
404501
405@summit_required502@summit_required
406def share_meeting(request, summit, attendee, meeting_id, meeting_slug):503def share_meeting(request, summit, attendee, meeting_id, meeting_slug):
@@ -409,30 +506,62 @@
409 # check if the user should be able to see this private meeting506 # check if the user should be able to see this private meeting
410 if attendee is None:507 if attendee is None:
411 raise Http404508 raise Http404
412 509
413 attendee_allowed = False510 attendee_allowed = False
414 for a in meeting.attendees:511 for a in meeting.attendees:
415 if a.user.pk == attendee.user.pk:512 if a.user.pk == attendee.user.pk:
416 meeting.share()513 meeting.share()
417 return HttpResponseRedirect(reverse(private_meeting, args=[summit.name, meeting.private_key, meeting_slug]))514 return HttpResponseRedirect(
515 reverse(
516 private_meeting,
517 args=[summit.name, meeting.private_key, meeting_slug]
518 )
519 )
418 raise Http404520 raise Http404
419 return HttpResponseRedirect(reverse(meeting, summit.name, meeting.id, meeting_slug))521 return HttpResponseRedirect(
420 522 reverse(
523 meeting,
524 summit.name,
525 meeting.id,
526 meeting_slug
527 )
528 )
529
530
421@summit_attendee_required531@summit_attendee_required
422def register(request, summit, attendee, meeting_id, meeting_slug):532def register(request, summit, attendee, meeting_id, meeting_slug):
423 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)533 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
424 user_is_attending = attendee is not None and attendee in meeting.attendees534 user_is_attending = attendee is not None and attendee in meeting.attendees
425 if not user_is_attending:535 if not user_is_attending:
426 meeting.participant_set.create(attendee=attendee, participation = 'ATTENDING', from_launchpad=False)536 meeting.participant_set.create(
427537 attendee=attendee,
428 return HttpResponseRedirect(reverse('summit.schedule.views.meeting', args=(summit.name, meeting.id, meeting_slug)))538 participation='ATTENDING',
539 from_launchpad=False
540 )
541
542 return HttpResponseRedirect(
543 reverse(
544 'summit.schedule.views.meeting',
545 args=(summit.name, meeting.id, meeting_slug)
546 )
547 )
548
429549
430@summit_attendee_required550@summit_attendee_required
431def unregister(request, summit, attendee, meeting_id, meeting_slug):551def unregister(request, summit, attendee, meeting_id, meeting_slug):
432 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)552 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
433 meeting.participant_set.filter(attendee=attendee, from_launchpad=False).delete()553 meeting.participant_set.filter(
434554 attendee=attendee,
435 return HttpResponseRedirect(reverse('summit.schedule.views.meeting', args=(summit.name, meeting.id, meeting_slug)))555 from_launchpad=False
556 ).delete()
557
558 return HttpResponseRedirect(
559 reverse(
560 'summit.schedule.views.meeting',
561 args=(summit.name, meeting.id, meeting_slug)
562 )
563 )
564
436565
437@summit_only_required566@summit_only_required
438def csv(request, summit):567def csv(request, summit):
@@ -442,70 +571,82 @@
442 return HttpResponse(schedule.as_csv(),571 return HttpResponse(schedule.as_csv(),
443 mimetype='text/csv')572 mimetype='text/csv')
444573
574
445@summit_only_required575@summit_only_required
446def ical(request, summit):576def ical(request, summit):
447 """Return any list events as an ical"""577 """Return any list events as an ical"""
448 schedule = Schedule.from_request(request, summit)578 schedule = Schedule.from_request(request, summit)
449 schedule.calculate()579 schedule.calculate()
450 580
451 filename = "%s.ical" % summit.name.replace(' ', '-').lower()581 filename = "%s.ical" % summit.name.replace(' ', '-').lower()
452 response = HttpResponse(mimetype='text/calendar')582 response = HttpResponse(mimetype='text/calendar')
453 response['Content-Disposition'] = 'attachment; filename=%s' % filename.encode('ascii', 'replace')583 response['Content-Disposition'] = 'attachment; filename=%s' % filename.encode('ascii', 'replace')
454 response.write(schedule.as_ical())584 response.write(schedule.as_ical())
455 return response585 return response
456586
587
457@summit_only_required588@summit_only_required
458def user_ical(request, summit, username):589def user_ical(request, summit, username):
459 """Returns a user's registered events as an ical"""590 """Returns a user's registered events as an ical"""
460 schedule = Schedule.from_request(request, summit)591 schedule = Schedule.from_request(request, summit)
461 schedule.calculate()592 schedule.calculate()
462 593
463 filename = "%s_%s.ical" % (summit.name, username)594 filename = "%s_%s.ical" % (summit.name, username)
464 response = HttpResponse(mimetype='text/calendar')595 response = HttpResponse(mimetype='text/calendar')
465 response['Content-Disposition'] = 'attachment; filename=%s' % filename.replace(' ', '-').lower().encode('ascii', 'replace')596 response['Content-Disposition'] = 'attachment; filename=%s' % filename.replace(' ', '-').lower().encode('ascii', 'replace')
466 response.write(schedule.as_ical(only_username=username))597 response.write(schedule.as_ical(only_username=username))
467 return response598 return response
468 599
600
469@summit_only_required601@summit_only_required
470def user_private_ical(request, summit, secret_key):602def user_private_ical(request, summit, secret_key):
471 """Returns a user's registered events as an ical"""603 """Returns a user's registered events as an ical"""
472 attendee = get_object_or_404(Attendee, secret_key_id=secret_key)604 attendee = get_object_or_404(Attendee, secret_key_id=secret_key)
473 schedule = Schedule.from_request(request, summit, show_private=True)605 schedule = Schedule.from_request(request, summit, show_private=True)
474 schedule.calculate()606 schedule.calculate()
475 607
476 response = HttpResponse(mimetype='text/calendar')608 response = HttpResponse(mimetype='text/calendar')
477 response['Content-Disposition'] = 'attachment; filename=my_schedule_%s.ical' % attendee.secret_key609 response['Content-Disposition'] = 'attachment; filename=my_schedule_%s.ical' % attendee.secret_key
478 response.write(schedule.as_ical(only_username=attendee.user.username, show_private=True))610 response.write(
611 schedule.as_ical(
612 only_username=attendee.user.username,
613 show_private=True
614 )
615 )
479 return response616 return response
480 617
618
481@summit_only_required619@summit_only_required
482def room_ical(request, summit, room_name):620def room_ical(request, summit, room_name):
483 """Returns a room's events as an ical"""621 """Returns a room's events as an ical"""
484 schedule = Schedule.from_request(request, summit)622 schedule = Schedule.from_request(request, summit)
485 schedule.calculate()623 schedule.calculate()
486 624
487 filename = "%s_%s.ical" % (summit.name, room_name)625 filename = "%s_%s.ical" % (summit.name, room_name)
488 response = HttpResponse(mimetype='text/calendar')626 response = HttpResponse(mimetype='text/calendar')
489 response['Content-Disposition'] = 'attachment; filename=%s' % filename.replace(' ', '-').lower().encode('ascii', 'replace')627 response['Content-Disposition'] = 'attachment; filename=%s' % filename.replace(' ', '-').lower().encode('ascii', 'replace')
490 response.write(schedule.as_ical(only_room=room_name))628 response.write(schedule.as_ical(only_room=room_name))
491 return response629 return response
492 630
631
493@summit_only_required632@summit_only_required
494def track_ical(request, summit, track_slug):633def track_ical(request, summit, track_slug):
495 """Returns a track's events as an ical"""634 """Returns a track's events as an ical"""
496 schedule = Schedule.from_request(request, summit)635 schedule = Schedule.from_request(request, summit)
497 schedule.calculate()636 schedule.calculate()
498 637
499 filename = "%s_%s.ical" % (summit.name, track_slug)638 filename = "%s_%s.ical" % (summit.name, track_slug)
500 response = HttpResponse(mimetype='text/calendar')639 response = HttpResponse(mimetype='text/calendar')
501 response['Content-Disposition'] = 'attachment; filename=%s' % filename.replace(' ', '-').lower().encode('ascii', 'replace')640 response['Content-Disposition'] = 'attachment; filename=%s' % filename.replace(' ', '-').lower().encode('ascii', 'replace')
502 response.write(schedule.as_ical(only_track=track_slug))641 response.write(schedule.as_ical(only_track=track_slug))
503 return response642 return response
504 643
644
505def logout_view(request):645def logout_view(request):
506 logout(request)646 logout(request)
507 return HttpResponseRedirect('/')647 return HttpResponseRedirect('/')
508648
649
509@summit_required650@summit_required
510def mobile(request, summit, attendee):651def mobile(request, summit, attendee):
511 context = {652 context = {
@@ -514,6 +655,7 @@
514 }655 }
515 return render_to_response("schedule/mobile.html", context, RequestContext(request))656 return render_to_response("schedule/mobile.html", context, RequestContext(request))
516657
658
517def past(request):659def past(request):
518 pastsummit = Summit.on_site.filter(date_end__lte=datetime.date.today())660 pastsummit = Summit.on_site.filter(date_end__lte=datetime.date.today())
519 context = {661 context = {
@@ -522,15 +664,26 @@
522 return render_to_response("schedule/past_summit.html", context,664 return render_to_response("schedule/past_summit.html", context,
523 context_instance=RequestContext(request))665 context_instance=RequestContext(request))
524666
667
525@summit_attendee_required668@summit_attendee_required
526def create_meeting(request, summit, attendee):669def create_meeting(request, summit, attendee):
527670
528 if not summit.is_organizer(attendee):671 if not summit.is_organizer(attendee):
529 return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))672 return HttpResponseRedirect(
673 reverse(
674 'summit.schedule.views.summit',
675 args=(summit.name,)
676 )
677 )
530 else:678 else:
531 meeting = Meeting(summit=summit, approver=attendee, drafter=attendee, approved='APPROVED')679 meeting = Meeting(
532 680 summit=summit,
533 if request.method == 'POST': 681 approver=attendee,
682 drafter=attendee,
683 approved='APPROVED'
684 )
685
686 if request.method == 'POST':
534 form = CreateMeeting(data=request.POST, instance=meeting)687 form = CreateMeeting(data=request.POST, instance=meeting)
535 if form.is_valid():688 if form.is_valid():
536 form.save()689 form.save()
@@ -542,15 +695,21 @@
542 'summit': summit,695 'summit': summit,
543 'form': form,696 'form': form,
544 }697 }
545 return render_to_response('schedule/create_meeting.html', 698 return render_to_response('schedule/create_meeting.html',
546 context, RequestContext(request))699 context, RequestContext(request))
547700
701
548@summit_attendee_required702@summit_attendee_required
549def propose_meeting(request, summit, attendee):703def propose_meeting(request, summit, attendee):
550704
551 meeting = Meeting(summit=summit, drafter=attendee, private=False, approved='PENDING')705 meeting = Meeting(
706 summit=summit,
707 drafter=attendee,
708 private=False,
709 approved='PENDING'
710 )
552711
553 if request.method == 'POST': 712 if request.method == 'POST':
554 form = ProposeMeeting(data=request.POST, instance=meeting)713 form = ProposeMeeting(data=request.POST, instance=meeting)
555 if form.is_valid():714 if form.is_valid():
556 form.save()715 form.save()
@@ -562,17 +721,29 @@
562 'summit': summit,721 'summit': summit,
563 'form': form,722 'form': form,
564 }723 }
565 return render_to_response('schedule/propose_meeting.html', 724 return render_to_response('schedule/propose_meeting.html',
566 context, RequestContext(request))725 context, RequestContext(request))
567 726
727
568@summit_attendee_required728@summit_attendee_required
569def organizer_edit_meeting(request, summit, attendee, meeting_id, meeting_slug):729def organizer_edit_meeting(
730 request,
731 summit,
732 attendee,
733 meeting_id,
734 meeting_slug
735):
570 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)736 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
571 737
572 if not summit.is_organizer(attendee):738 if not summit.is_organizer(attendee):
573 return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))739 return HttpResponseRedirect(
740 reverse(
741 'summit.schedule.views.summit',
742 args=(summit.name,)
743 )
744 )
574 else:745 else:
575 if request.method == 'POST': 746 if request.method == 'POST':
576 form = OrganizerEditMeeting(data=request.POST, instance=meeting)747 form = OrganizerEditMeeting(data=request.POST, instance=meeting)
577 if form.is_valid():748 if form.is_valid():
578 form.save()749 form.save()
@@ -584,17 +755,23 @@
584 'summit': summit,755 'summit': summit,
585 'form': form,756 'form': form,
586 }757 }
587 return render_to_response('schedule/org_edit_meeting.html', 758 return render_to_response('schedule/org_edit_meeting.html',
588 context, RequestContext(request))759 context, RequestContext(request))
589760
761
590@summit_attendee_required762@summit_attendee_required
591def edit_meeting(request, summit, attendee, meeting_id, meeting_slug):763def edit_meeting(request, summit, attendee, meeting_id, meeting_slug):
592 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)764 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
593 765
594 if attendee != meeting.drafter:766 if attendee != meeting.drafter:
595 return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))767 return HttpResponseRedirect(
768 reverse(
769 'summit.schedule.views.summit',
770 args=(summit.name,)
771 )
772 )
596 else:773 else:
597 if request.method == 'POST': 774 if request.method == 'POST':
598 form = EditMeeting(data=request.POST, instance=meeting)775 form = EditMeeting(data=request.POST, instance=meeting)
599 if form.is_valid():776 if form.is_valid():
600 form.save()777 form.save()
@@ -606,14 +783,55 @@
606 'summit': summit,783 'summit': summit,
607 'form': form,784 'form': form,
608 }785 }
609 return render_to_response('schedule/edit_meeting.html', 786 return render_to_response('schedule/edit_meeting.html',
610 context, RequestContext(request))787 context, RequestContext(request))
788
789
790@summit_attendee_required
791def edit_meeting_hangout(
792 request,
793 summit,
794 attendee,
795 meeting_id,
796 meeting_slug
797):
798 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
799 # TODO: Add logic that prevents this view from being accessed if the
800 # Summit or meeting is not virtual
801 if not summit.is_organizer(attendee) and attendee != meeting.drafter:
802 return HttpResponseRedirect(
803 reverse(
804 'summit.schedule.views.summit',
805 args=(summit.name,)
806 )
807 )
808 else:
809 if request.method == 'POST':
810 form = EditMeetingHangout(data=request.POST, instance=meeting)
811 if form.is_valid():
812 form.save()
813 return HttpResponseRedirect(meeting.meeting_page_url)
814 else:
815 form = EditMeetingHangout(instance=meeting)
816
817 context = {
818 'summit': summit,
819 'form': form,
820 }
821 return render_to_response('schedule/edit_hangout.html',
822 context, RequestContext(request))
823
611824
612@summit_required825@summit_required
613def review_pending(request, summit, attendee):826def review_pending(request, summit, attendee):
614827
615 if not summit.is_organizer(attendee):828 if not summit.is_organizer(attendee):
616 return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))829 return HttpResponseRedirect(
830 reverse(
831 'summit.schedule.views.summit',
832 args=(summit.name,)
833 )
834 )
617 else:835 else:
618 schedule = SortedDict()836 schedule = SortedDict()
619837
@@ -632,12 +850,18 @@
632 return render_to_response("schedule/review.html", context,850 return render_to_response("schedule/review.html", context,
633 context_instance=RequestContext(request))851 context_instance=RequestContext(request))
634852
853
635@summit_required854@summit_required
636def meeting_review(request, summit, attendee, meeting_id):855def meeting_review(request, summit, attendee, meeting_id):
637 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)856 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
638857
639 if not summit.is_organizer(attendee):858 if not summit.is_organizer(attendee):
640 return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))859 return HttpResponseRedirect(
860 reverse(
861 'summit.schedule.views.summit',
862 args=(summit.name,)
863 )
864 )
641 else:865 else:
642 if request.method == 'POST':866 if request.method == 'POST':
643 form = MeetingReview(data=request.POST, instance=meeting)867 form = MeetingReview(data=request.POST, instance=meeting)
@@ -656,12 +880,19 @@
656 return render_to_response('schedule/meeting_review.html',880 return render_to_response('schedule/meeting_review.html',
657 context, RequestContext(request))881 context, RequestContext(request))
658882
883
659@summit_required884@summit_required
660def created_meetings(request, summit, attendee, username):885def created_meetings(request, summit, attendee, username):
661886
662 drafter = get_object_or_404(Attendee, summit=summit, user__username=username)887 drafter = get_object_or_404(
888 Attendee,
889 summit=summit,
890 user__username=username
891 )
663 if attendee is None or attendee.id != drafter.id:892 if attendee is None or attendee.id != drafter.id:
664 meetings = summit.meeting_set.filter(drafter=drafter).exclude(private=True)893 meetings = summit.meeting_set.filter(
894 drafter=drafter
895 ).exclude(private=True)
665 else:896 else:
666 meetings = summit.meeting_set.filter(drafter=drafter)897 meetings = summit.meeting_set.filter(drafter=drafter)
667898
@@ -674,12 +905,18 @@
674 return render_to_response("schedule/mine.html", context,905 return render_to_response("schedule/mine.html", context,
675 context_instance=RequestContext(request))906 context_instance=RequestContext(request))
676907
908
677@summit_required909@summit_required
678def meeting_copy(request, summit, attendee, meeting_id, meeting_slug):910def meeting_copy(request, summit, attendee, meeting_id, meeting_slug):
679 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)911 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
680912
681 if not summit.can_change_agenda(attendee):913 if not summit.can_change_agenda(attendee):
682 return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))914 return HttpResponseRedirect(
915 reverse(
916 'summit.schedule.views.summit',
917 args=(summit.name,)
918 )
919 )
683 else:920 else:
684 if request.method == 'POST':921 if request.method == 'POST':
685 form = CreateMeeting(instance=meeting, data=request.POST)922 form = CreateMeeting(instance=meeting, data=request.POST)
@@ -692,7 +929,6 @@
692 meeting = form.save()929 meeting = form.save()
693 meeting_id = meeting.id930 meeting_id = meeting.id
694 return HttpResponseRedirect(meeting.meeting_page_url)931 return HttpResponseRedirect(meeting.meeting_page_url)
695
696 else:932 else:
697 form = CreateMeeting(instance=meeting)933 form = CreateMeeting(instance=meeting)
698934
@@ -700,19 +936,23 @@
700 'summit': summit,936 'summit': summit,
701 'form': form,937 'form': form,
702 }938 }
703 939
704 return render_to_response('schedule/create_meeting.html', 940 return render_to_response('schedule/create_meeting.html',
705 context, RequestContext(request))941 context, RequestContext(request))
706942
943
707@summit_attendee_required944@summit_attendee_required
708def attend_meeting(request, summit, attendee, meeting_id):945def attend_meeting(request, summit, attendee, meeting_id):
709 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)946 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
710947
711 try:948 try:
712 participant = Participant.objects.get(attendee=attendee, meeting=meeting)949 participant = Participant.objects.get(
950 attendee=attendee,
951 meeting=meeting
952 )
713 except Participant.DoesNotExist:953 except Participant.DoesNotExist:
714 participant = Participant(attendee=attendee, meeting=meeting)954 participant = Participant(attendee=attendee, meeting=meeting)
715 955
716 if request.method == 'POST':956 if request.method == 'POST':
717 form = AttendMeeting(data=request.POST, instance=participant)957 form = AttendMeeting(data=request.POST, instance=participant)
718 if form.is_valid():958 if form.is_valid():
@@ -731,44 +971,79 @@
731 return render_to_response('schedule/attend.html',971 return render_to_response('schedule/attend.html',
732 context, RequestContext(request))972 context, RequestContext(request))
733973
974
734@summit_required975@summit_required
735def attendee_review(request, summit, attendee, meeting_slug, meeting_id):976def attendee_review(request, summit, attendee, meeting_slug, meeting_id):
736 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)977 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
737978
738 if not summit.is_organizer(attendee) and attendee != meeting.drafter:979 if not summit.is_organizer(attendee) and attendee != meeting.drafter:
739 return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))980 return HttpResponseRedirect(
981 reverse(
982 'summit.schedule.views.summit',
983 args=(summit.name,)
984 )
985 )
740 else:986 else:
741 participants = meeting.participant_set.all()987 participants = meeting.participant_set.all()
742988
743 context = {989 context = {
744 'summit': summit,990 'summit': summit,
745 'meeting':meeting,991 'meeting': meeting,
746 'participants':participants,992 'participants': participants,
747 'summit_organizer': summit.is_organizer(attendee),993 'summit_organizer': summit.is_organizer(attendee),
748994
749 }995 }
750 return render_to_response("schedule/attendees.html", context,996 return render_to_response("schedule/attendees.html", context,
751 context_instance=RequestContext(request))997 context_instance=RequestContext(request))
752998
999
753@summit_attendee_required1000@summit_attendee_required
754def organizer_edit_attendees(request, summit, logged_in_user, username, meeting_id):1001def organizer_edit_attendees(
1002 request,
1003 summit,
1004 logged_in_user,
1005 username,
1006 meeting_id
1007):
755 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)1008 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
756 attendee = get_object_or_404(Attendee, summit=summit, user__username=username)1009 attendee = get_object_or_404(
1010 Attendee,
1011 summit=summit,
1012 user__username=username
1013 )
757 meeting_slug = get_object_or_404(Meeting, summit=summit, id=meeting_id)1014 meeting_slug = get_object_or_404(Meeting, summit=summit, id=meeting_id)
7581015
759 if not summit.is_organizer(logged_in_user) and logged_in_user != meeting.drafter:1016 if not summit.is_organizer(
760 return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))1017 logged_in_user
1018 ) and logged_in_user != meeting.drafter:
1019 return HttpResponseRedirect(
1020 reverse(
1021 'summit.schedule.views.summit',
1022 args=(summit.name,)
1023 )
1024 )
761 else:1025 else:
762 try:1026 try:
763 participant = Participant.objects.get(attendee=attendee, meeting=meeting)1027 participant = Participant.objects.get(
1028 attendee=attendee,
1029 meeting=meeting
1030 )
764 except Participant.DoesNotExist:1031 except Participant.DoesNotExist:
765 participant = Participant(attendee=attendee, meeting=meeting)1032 participant = Participant(attendee=attendee, meeting=meeting)
766 1033
767 if request.method == 'POST':1034 if request.method == 'POST':
768 form = OrganizerChangeAttend(data=request.POST, instance=participant)1035 form = OrganizerChangeAttend(
1036 data=request.POST,
1037 instance=participant
1038 )
769 if form.is_valid():1039 if form.is_valid():
770 form.save()1040 form.save()
771 return HttpResponseRedirect(reverse('summit.schedule.views.attendee_review', args=(summit.name, meeting.id, meeting.name)))1041 return HttpResponseRedirect(
1042 reverse(
1043 'summit.schedule.views.attendee_review',
1044 args=(summit.name, meeting.id, meeting.name)
1045 )
1046 )
772 else:1047 else:
773 form = OrganizerChangeAttend(instance=participant)1048 form = OrganizerChangeAttend(instance=participant)
7741049
@@ -784,11 +1059,22 @@
7841059
7851060
786@summit_attendee_required1061@summit_attendee_required
787def delete_meeting_confirm(request, summit, attendee, meeting_id, meeting_slug):1062def delete_meeting_confirm(
1063 request,
1064 summit,
1065 attendee,
1066 meeting_id,
1067 meeting_slug
1068):
788 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)1069 meeting = get_object_or_404(summit.meeting_set, id=meeting_id)
789 1070
790 if not attendee.user in summit.schedulers.all() and not attendee.user.has_perm('schedule.change_agenda'):1071 if not attendee.user in summit.schedulers.all() and not attendee.user.has_perm('schedule.change_agenda'):
791 return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))1072 return HttpResponseRedirect(
1073 reverse(
1074 'summit.schedule.views.summit',
1075 args=(summit.name,)
1076 )
1077 )
7921078
793 context = {1079 context = {
794 'summit': summit,1080 'summit': summit,
@@ -801,18 +1087,29 @@
8011087
802@summit_attendee_required1088@summit_attendee_required
803def delete_meeting(request, summit, attendee, meeting_id, meeting_slug):1089def delete_meeting(request, summit, attendee, meeting_id, meeting_slug):
804 meeting = get_object_or_404(summit.meeting_set, pk = meeting_id)1090 meeting = get_object_or_404(summit.meeting_set, pk=meeting_id)
805 if not attendee.user in summit.schedulers.all() and not attendee.user.has_perm('schedule.change_agenda'):1091 if not attendee.user in summit.schedulers.all() and not attendee.user.has_perm('schedule.change_agenda'):
806 return HttpResponseRedirect(reverse('summit.schedule.views.summit', args=(summit.name,)))1092 return HttpResponseRedirect(
1093 reverse(
1094 'summit.schedule.views.summit',
1095 args=(summit.name,)
1096 )
1097 )
807 else:1098 else:
808 meeting.approved = 'REMOVED'1099 meeting.approved = 'REMOVED'
809 meeting.save()1100 meeting.save()
810 meeting.agenda_set.all().delete()1101 meeting.agenda_set.all().delete()
811 return HttpResponseRedirect(reverse('summit.schedule.views.delete_confirmed', args=(summit.name,)))1102 return HttpResponseRedirect(
1103 reverse(
1104 'summit.schedule.views.delete_confirmed',
1105 args=(summit.name,)
1106 )
1107 )
1108
8121109
813def delete_confirmed(request, summit_name):1110def delete_confirmed(request, summit_name):
814 summit = get_object_or_404(Summit, name=summit_name)1111 summit = get_object_or_404(Summit, name=summit_name)
815 1112
816 context = {1113 context = {
817 'summit': summit1114 'summit': summit
818 }1115 }
8191116
=== modified file 'summit/urls.py'
--- summit/urls.py 2012-10-26 09:32:11 +0000
+++ summit/urls.py 2013-02-22 01:25:24 +0000
@@ -16,7 +16,6 @@
1616
17from django.conf.urls.defaults import *17from django.conf.urls.defaults import *
18from django.conf import settings18from django.conf import settings
19import ubuntu_website
2019
21from common.views import login_failure20from common.views import login_failure
2221
@@ -24,13 +23,15 @@
24admin.autodiscover()23admin.autodiscover()
2524
2625
27urlpatterns = patterns('',26urlpatterns = patterns(
27 '',
28 (r'^$', 'summit.common.views.index'),28 (r'^$', 'summit.common.views.index'),
29 (r'^admin/', admin.site.urls),29 (r'^admin/', admin.site.urls),
30 (r'^api/', include('services.urls')),30 (r'^api/', include('services.urls')),
31)31)
3232
33urlpatterns += patterns('django_openid_auth.views',33urlpatterns += patterns(
34 'django_openid_auth.views',
34 url(r'^openid/login/$', 'login_begin', name='openid-login',35 url(r'^openid/login/$', 'login_begin', name='openid-login',
35 kwargs={'render_failure': login_failure}),36 kwargs={'render_failure': login_failure}),
36 url(r'^openid/complete/$', 'login_complete', name='openid-complete',37 url(r'^openid/complete/$', 'login_complete', name='openid-complete',
@@ -38,19 +39,17 @@
38 url(r'^openid/logo.gif$', 'logo', name='openid-logo'),39 url(r'^openid/logo.gif$', 'logo', name='openid-logo'),
39)40)
4041
41urlpatterns += patterns('summit.sponsor.views',42urlpatterns += patterns(
43 'summit.sponsor.views',
42 (r'^(?P<summit_name>[\w-]+)/sponsorship/$', 'sponsorship'),44 (r'^(?P<summit_name>[\w-]+)/sponsorship/$', 'sponsorship'),
43 (r'^(?P<summit_name>[\w-]+)/sponsorship/done/$', 'done'),45 (r'^(?P<summit_name>[\w-]+)/sponsorship/done/$', 'done'),
44 (r'^(?P<summit_name>[\w-]+)/sponsorship/review/$', 'review_list'),46 (r'^(?P<summit_name>[\w-]+)/sponsorship/review/$', 'review_list'),
45
46 (r'^(?P<summit_name>[\w-]+)/suggestsponsorship/$', 'suggestsponsorship'),47 (r'^(?P<summit_name>[\w-]+)/suggestsponsorship/$', 'suggestsponsorship'),
47 (r'^(?P<summit_name>[\w-]+)/suggestsponsorship/done/$', 'suggestiondone'),48 (r'^(?P<summit_name>[\w-]+)/suggestsponsorship/done/$', 'suggestiondone'),
48
49 (r'^(?P<summit_name>[\w-]+)/nonlaunchpadsponsorship/$',49 (r'^(?P<summit_name>[\w-]+)/nonlaunchpadsponsorship/$',
50 'nonlaunchpadsponsorship'),50 'nonlaunchpadsponsorship'),
51 (r'^(?P<summit_name>[\w-]+)/nonlaunchpadsponsorship/done/$',51 (r'^(?P<summit_name>[\w-]+)/nonlaunchpadsponsorship/done/$',
52 'nonlaunchpaddone'),52 'nonlaunchpaddone'),
53
54 (r'^(?P<summit_name>[\w-]+)/sponsorship/review/(?P<sponsorship_id>[0-9]+)$',53 (r'^(?P<summit_name>[\w-]+)/sponsorship/review/(?P<sponsorship_id>[0-9]+)$',
55 'review'),54 'review'),
56 (r'^(?P<summit_name>[\w-]+)/suggestedsponsorship/review/(?P<sponsorship_id>[0-9]+)$',55 (r'^(?P<summit_name>[\w-]+)/suggestedsponsorship/review/(?P<sponsorship_id>[0-9]+)$',
@@ -61,7 +60,8 @@
61 (r'^(?P<summit_name>[\w-]+)/sponsorship/export/$', 'export'),60 (r'^(?P<summit_name>[\w-]+)/sponsorship/export/$', 'export'),
62)61)
6362
64urlpatterns += patterns('summit.schedule.views',63urlpatterns += patterns(
64 'summit.schedule.views',
65 url(r'^today/(?P<summit_name>[\w-]+)/$', 'today_view', name='today'),65 url(r'^today/(?P<summit_name>[\w-]+)/$', 'today_view', name='today'),
66 url(r'^past/', 'past', name='past'),66 url(r'^past/', 'past', name='past'),
67 url(r'^logout$', 'logout_view', name='logout'),67 url(r'^logout$', 'logout_view', name='logout'),
@@ -69,42 +69,66 @@
69 (r'^(?P<summit_name>[\w-]+)/mobile/$', 'mobile'),69 (r'^(?P<summit_name>[\w-]+)/mobile/$', 'mobile'),
70 (r'^(?P<summit_name>[\w-]+)/search/$', 'search'),70 (r'^(?P<summit_name>[\w-]+)/search/$', 'search'),
71 (r'^(?P<summit_name>[\w-]+)/propose_meeting/$', 'propose_meeting'),71 (r'^(?P<summit_name>[\w-]+)/propose_meeting/$', 'propose_meeting'),
72 (r'^(?P<summit_name>[\w-]+)/edit_meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', 'edit_meeting'),72 (r'^(?P<summit_name>[\w-]+)/edit_meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
73 'edit_meeting'),
73 (r'^(?P<summit_name>[\w-]+)/review/$', 'review_pending'),74 (r'^(?P<summit_name>[\w-]+)/review/$', 'review_pending'),
74 (r'^(?P<summit_name>[\w-]+)/review_meeting/(?P<meeting_id>\d+)/$', 'meeting_review'),75 (r'^(?P<summit_name>[\w-]+)/review_meeting/(?P<meeting_id>\d+)/$',
75 (r'^(?P<summit_name>[\w-]+)/attend_meeting/(?P<meeting_id>\d+)/$', 'attend_meeting'),76 'meeting_review'),
76 (r'^(?P<summit_name>[\w-]+)/edit_attendee/(?P<meeting_id>\d+)/(?P<username>[%+\.\w-]+)/$', 'organizer_edit_attendees'),77 (r'^(?P<summit_name>[\w-]+)/attend_meeting/(?P<meeting_id>\d+)/$',
78 'attend_meeting'),
79 (r'^(?P<summit_name>[\w-]+)/edit_attendee/(?P<meeting_id>\d+)/(?P<username>[%+\.\w-]+)/$',
80 'organizer_edit_attendees'),
77 (r'^(?P<summit_name>[\w-]+)/create_meeting/$', 'create_meeting'),81 (r'^(?P<summit_name>[\w-]+)/create_meeting/$', 'create_meeting'),
78 (r'^(?P<summit_name>[\w-]+)/edit_mtg/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', 'organizer_edit_meeting'),82 (r'^(?P<summit_name>[\w-]+)/edit_mtg/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
79 (r'^(?P<summit_name>[\w-]+)/confirm_del_mtg/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', 'delete_meeting_confirm'),83 'organizer_edit_meeting'),
80 (r'^(?P<summit_name>[\w-]+)/del_mtg/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', 'delete_meeting'),84 (r'^(?P<summit_name>[\w-]+)/hangout/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
85 'edit_meeting_hangout'),
86 (r'^(?P<summit_name>[\w-]+)/confirm_del_mtg/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
87 'delete_meeting_confirm'),
88 (r'^(?P<summit_name>[\w-]+)/del_mtg/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
89 'delete_meeting'),
81 (r'^(?P<summit_name>[\w-]+)/deleted/$', 'delete_confirmed'),90 (r'^(?P<summit_name>[\w-]+)/deleted/$', 'delete_confirmed'),
82 (r'^(?P<summit_name>[\w-]+)/attendee_review/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', 'attendee_review'),91 (r'^(?P<summit_name>[\w-]+)/attendee_review/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
92 'attendee_review'),
83 (r'^(?P<summit_name>[\w-]+)/tracks$', 'tracks'),93 (r'^(?P<summit_name>[\w-]+)/tracks$', 'tracks'),
84 (r'^(?P<summit_name>[\w-]+)/next$', 'next_session'),94 (r'^(?P<summit_name>[\w-]+)/next$', 'next_session'),
85 (r'^(?P<summit_name>[\w-]+)/next_table$', 'next_table'),95 (r'^(?P<summit_name>[\w-]+)/next_table$', 'next_table'),
86 (r'^(?P<summit_name>[\w-]+)/(?P<username>[%+\.\w-]+)/meetings$', 'created_meetings'),96 (r'^(?P<summit_name>[\w-]+)/(?P<username>[%+\.\w-]+)/meetings$',
97 'created_meetings'),
87 (r'^(?P<summit_name>[\w-]+)/(?P<date>[\d-]+)/$', 'daily_schedule'),98 (r'^(?P<summit_name>[\w-]+)/(?P<date>[\d-]+)/$', 'daily_schedule'),
88 (r'^(?P<summit_name>[\w-]+)/(?P<date>[\d-]+)/display$', 'by_date'),99 (r'^(?P<summit_name>[\w-]+)/(?P<date>[\d-]+)/display$', 'by_date'),
89 (r'^(?P<summit_name>[\w-]+)/(?P<room_name>[%+\.\w-]+)/$', 'by_room'),100 (r'^(?P<summit_name>[\w-]+)/(?P<room_name>[%+\.\w-]+)/$', 'by_room'),
90 (r'^(?P<summit_name>[\w-]+)/track/(?P<track_slug>[%+\.\w-]+)/$', 'by_track'),101 (r'^(?P<summit_name>[\w-]+)/track/(?P<track_slug>[%+\.\w-]+)/$',
91 (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/\+share$', 'share_meeting'),102 'by_track'),
92 (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/\+register', 'register'),103 (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/\+share$',
93 (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/\+unregister', 'unregister'),104 'share_meeting'),
94 (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$', 'meeting'),105 (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/\+register',
95 (r'^(?P<summit_name>[\w-]+)/private/(?P<private_key>[0-9a-f]{32})/(?P<meeting_slug>[%+\.\w-]+)/$', 'private_meeting'),106 'register'),
96 (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/copy/$', 'meeting_copy'),107 (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/\+unregister',
108 'unregister'),
109 (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/$',
110 'meeting'),
111 (r'^(?P<summit_name>[\w-]+)/private/(?P<private_key>[0-9a-f]{32})/(?P<meeting_slug>[%+\.\w-]+)/$',
112 'private_meeting'),
113 (r'^(?P<summit_name>[\w-]+)/meeting/(?P<meeting_id>\d+)/(?P<meeting_slug>[%+\.\w-]+)/copy/$',
114 'meeting_copy'),
97 (r'^(?P<summit_name>[\w-]+)\.csv$', 'csv'),115 (r'^(?P<summit_name>[\w-]+)\.csv$', 'csv'),
98 (r'^(?P<summit_name>[\w-]+)\.ical$', 'ical'),116 (r'^(?P<summit_name>[\w-]+)\.ical$', 'ical'),
99 (r'^(?P<summit_name>[\w-]+)/participant/(?P<username>[%+\.\w-]+)/$', 'by_participant'),117 (r'^(?P<summit_name>[\w-]+)/participant/(?P<username>[%+\.\w-]+)/$',
100 (r'^(?P<summit_name>[\w-]+)/participant/my_schedule_(?P<secret_key>[0-9a-f]{32})\.ical$', 'user_private_ical'),118 'by_participant'),
101 (r'^(?P<summit_name>[\w-]+)/participant/(?P<username>[%+\.\w-]+)\.ical$', 'user_ical'),119 (r'^(?P<summit_name>[\w-]+)/participant/my_schedule_(?P<secret_key>[0-9a-f]{32})\.ical$',
102 (r'^(?P<summit_name>[\w-]+)/room/(?P<room_name>[%+\.\w-]+).ical$', 'room_ical'),120 'user_private_ical'),
103 (r'^(?P<summit_name>[\w-]+)/track/(?P<track_slug>[%+\.\w-]+).ical$', 'track_ical'),121 (r'^(?P<summit_name>[\w-]+)/participant/(?P<username>[%+\.\w-]+)\.ical$',
122 'user_ical'),
123 (r'^(?P<summit_name>[\w-]+)/room/(?P<room_name>[%+\.\w-]+).ical$',
124 'room_ical'),
125 (r'^(?P<summit_name>[\w-]+)/track/(?P<track_slug>[%+\.\w-]+).ical$',
126 'track_ical'),
104)127)
105128
106if settings.DEBUG or settings.SERVE_STATIC:129if settings.DEBUG or settings.SERVE_STATIC:
107 urlpatterns += patterns('',130 urlpatterns += patterns(
131 '',
108 (r'^media/(?P<path>.*)$', 'django.views.static.serve',132 (r'^media/(?P<path>.*)$', 'django.views.static.serve',
109 {'document_root': settings.MEDIA_ROOT}),133 {'document_root': settings.MEDIA_ROOT}),
110 (r'^(robots.txt)$', 'django.views.static.serve',134 (r'^(robots.txt)$', 'django.views.static.serve',

Subscribers

People subscribed via source and target branches