Merge lp:~mhall119/summit/menu-fixes into lp:~cjohnston/summit/menu-fixes

Proposed by Chris Johnston
Status: Merged
Merge reported by: Chris Johnston
Merged at revision: not available
Proposed branch: lp:~mhall119/summit/menu-fixes
Merge into: lp:~cjohnston/summit/menu-fixes
Diff against target: 618 lines (+332/-32) (has conflicts)
9 files modified
summit/common/management/commands/lpupdate.py (+11/-2)
summit/common/templatetags/menubuilder.py (+13/-0)
summit/common/tests.py (+11/-0)
summit/schedule/admin/meetingadmin.py (+1/-1)
summit/schedule/management/commands/initslots.py (+14/-6)
summit/schedule/migrations/0025_add_meeting_blueprint_id.py (+207/-0)
summit/schedule/models/meetingmodel.py (+8/-0)
summit/schedule/models/summitmodel.py (+32/-15)
summit/schedule/tests.py (+35/-8)
Text conflict in summit/common/templatetags/menubuilder.py
Text conflict in summit/common/tests.py
To merge this branch: bzr merge lp:~mhall119/summit/menu-fixes
Reviewer Review Type Date Requested Status
Chris Johnston Pending
Review via email: mp+127885@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'summit/common/management/commands/lpupdate.py'
2--- summit/common/management/commands/lpupdate.py 2012-02-25 00:13:45 +0000
3+++ summit/common/management/commands/lpupdate.py 2012-10-03 21:15:28 +0000
4@@ -17,6 +17,7 @@
5 from django.core.management.base import BaseCommand, CommandError
6
7 from summit.schedule.models import Summit
8+from optparse import make_option
9
10 __all__ = (
11 'Command',
12@@ -24,16 +25,24 @@
13
14
15 class Command(BaseCommand):
16+ option_list = BaseCommand.option_list + (
17+ make_option("-s", "--slots", dest="slots",
18+ help="Number of slots an imported meeting needs", type=int, default=1),
19+ make_option("-A", "--no-attendees", dest="skip_attendees", action="store_true",
20+ help="Don't import Attendee data", default=False),
21+ make_option("-M", "--no-meetings", dest="skip_meetings", action="store_true",
22+ help="Don't import Meeting data", default=False),
23+ )
24
25 def handle(self, summit='', *args, **options):
26 if not summit:
27 for summit in Summit.objects.all():
28 print "Updating %s" % summit
29- summit.update_from_launchpad()
30+ summit.update_from_launchpad(options)
31 else:
32 try:
33 summit = Summit.objects.get(name=summit)
34 except Summit.DoesNotExist:
35 raise CommandError("Summit doesn't exist: %s" % summit)
36 print "Updating %s" % summit
37- summit.update_from_launchpad()
38+ summit.update_from_launchpad(options)
39
40=== modified file 'summit/common/templatetags/menubuilder.py'
41--- summit/common/templatetags/menubuilder.py 2012-10-03 21:01:17 +0000
42+++ summit/common/templatetags/menubuilder.py 2012-10-03 21:15:28 +0000
43@@ -70,6 +70,7 @@
44 menuitems = []
45
46 try:
47+<<<<<<< TREE
48 menu = Menu.objects.get(slug=menu_name)
49 except Menu.DoesNotExist:
50 return []
51@@ -85,6 +86,18 @@
52
53 if cache_time >= 0 and not debug:
54 cache.set(cache_key, menuitems, cache_time)
55+=======
56+ menu_instance = Menu.objects.get(slug=menu)
57+ base_path = menu_instance.base_url or ''
58+ for i in MenuItem.objects.filter(menu=menu_instance).order_by('order'):
59+ current = ( i.link_url != '/' and current_path == (base_path + i.link_url)) or ( i.link_url == '/' and current_path == '/' )
60+ if not i.login_required or ( i.login_required and user.is_authenticated() ):
61+ menuitems.append({'url': i.link_url, 'title': i.title, 'current': current,})
62+ except Menu.DoesNotExist:
63+ pass# No Menu by this name, fail gracefully
64+ except MenuItem.DoesNotExist:
65+ pass# No Menu by this name, fail gracefully
66+>>>>>>> MERGE-SOURCE
67 return menuitems
68
69 register.tag('menu', build_menu)
70
71=== modified file 'summit/common/tests.py'
72--- summit/common/tests.py 2012-10-03 21:01:17 +0000
73+++ summit/common/tests.py 2012-10-03 21:15:28 +0000
74@@ -44,6 +44,7 @@
75
76 def test_toplevel_menu_highlights(self):
77 schedule_page = self.client.get('/uds-test/')
78+<<<<<<< TREE
79 print schedule_page.content
80 self.assertContains(schedule_page,
81 '<li class=\'active\' id="main-nav"><a class="main-nav-item" href="/uds-test/" title="Schedule">Schedule</a>', 1)
82@@ -53,6 +54,16 @@
83 '<li class=\'active\' id="main-nav"><a class="main-nav-item" href="/today/uds-test/" title="Today">Today</a>', 0)
84 self.assertContains(schedule_page,
85 '<li id="main-nav"><a class="main-nav-item" href="/today/uds-test/" title="Today">Today</a>', 1)
86+=======
87+ self.assertContains(schedule_page,
88+ '<li class=\'active\' id="main-nav"><a class="main-nav-item" href="/uds-test/" title="Schedule">Schedule</a>', 1)
89+ self.assertContains(schedule_page,
90+ '<li id="main-nav"><a class="main-nav-item" href="/uds-test/" title="Schedule">Schedule</a>', 0)
91+ self.assertContains(schedule_page,
92+ '<li class=\'active\' id="main-nav"><a class="main-nav-item" href="/today/uds-test/" title="Today">Today</a>', 0)
93+ self.assertContains(schedule_page,
94+ '<li id="main-nav"><a class="main-nav-item" href="/today/uds-test/" title="Today">Today</a>', 1)
95+>>>>>>> MERGE-SOURCE
96
97 def test_sublevel_menu_highlights(self):
98 today_page = self.client.get('/today/uds-test/')
99
100=== modified file 'summit/schedule/admin/meetingadmin.py'
101--- summit/schedule/admin/meetingadmin.py 2012-05-16 14:59:59 +0000
102+++ summit/schedule/admin/meetingadmin.py 2012-10-03 21:15:28 +0000
103@@ -144,7 +144,7 @@
104 'type', 'tracks', 'requires_dial_in', 'video'),
105 }),
106 ("References", {
107- 'fields': ('spec_url', 'wiki_url', 'pad_url'),
108+ 'fields': ('spec_url', 'launchpad_blueprint_id', 'wiki_url', 'pad_url'),
109 }),
110 ("Scheduling details", {
111 'classes': ('collapse', ),
112
113=== modified file 'summit/schedule/management/commands/initslots.py'
114--- summit/schedule/management/commands/initslots.py 2012-03-08 22:19:17 +0000
115+++ summit/schedule/management/commands/initslots.py 2012-10-03 21:15:28 +0000
116@@ -58,6 +58,9 @@
117 duration = datetime.timedelta(minutes=options["duration"])
118 interval = datetime.timedelta(minutes=options["interval"])
119 breaktime = datetime.timedelta(minutes=15)
120+
121+ slots_per_hour = (60 * 60) / duration.seconds
122+
123 try:
124 summit = Summit.objects.get(name=summit.__str__)
125 except Summit.DoesNotExist:
126@@ -77,14 +80,19 @@
127 # Determines the type of the session
128 if slottime.time() == lunch:
129 slot_type = 'lunch'
130+ slot_duration = datetime.timedelta(minutes=60)
131+ slot_count += (slots_per_hour - 1)
132 elif slottime.time() == plenary:
133 slot_type = 'plenary'
134+ slot_duration = datetime.timedelta(minutes=60)
135+ slot_count += (slots_per_hour - 1)
136 else:
137 slot_type = 'open'
138- slot_length = duration
139+ slot_duration = duration
140+ slot_length = slot_duration
141
142 # Morning Break
143- if slot_count == 2:
144+ if slot_count == (2 * slots_per_hour):
145 slot, created = Slot.objects.get_or_create(
146 summit=summit,
147 start_utc=start_time + slot_length - breaktime,
148@@ -93,7 +101,7 @@
149 )
150 slot_length = slot_length - breaktime
151 # Afternoon Break
152- elif slot_count == 8:
153+ elif slot_count == (7 * slots_per_hour)+1:
154 slot, created = Slot.objects.get_or_create(
155 summit=summit,
156 start_utc=start_time,
157@@ -105,10 +113,10 @@
158 slottime = slottime + interval
159 # Non-break intervals
160 elif slot_type == 'open':
161- nexthour = slottime + hour
162+ nexthour = slottime + duration
163 if nexthour.time() != lunch \
164 and nexthour.time() != plenary \
165- and slot_count != 7:
166+ and slot_count != (7*slots_per_hour):
167 slot_length = slot_length - interval
168
169 end_time = start_time + slot_length
170@@ -120,7 +128,7 @@
171 end_utc=end_time,
172 type=slot_type)
173
174- slottime = slottime + duration
175+ slottime = slottime + slot_duration
176
177 date = date + day
178 print "Initializing slots complete."
179
180=== added file 'summit/schedule/migrations/0025_add_meeting_blueprint_id.py'
181--- summit/schedule/migrations/0025_add_meeting_blueprint_id.py 1970-01-01 00:00:00 +0000
182+++ summit/schedule/migrations/0025_add_meeting_blueprint_id.py 2012-10-03 21:15:28 +0000
183@@ -0,0 +1,207 @@
184+# encoding: utf-8
185+import datetime
186+from south.db import db
187+from south.v2 import SchemaMigration
188+from django.db import models
189+
190+class Migration(SchemaMigration):
191+
192+ def forwards(self, orm):
193+
194+ # Adding field 'Meeting.launchpad_blueprint_id'
195+ db.add_column('schedule_meeting', 'launchpad_blueprint_id', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True), keep_default=False)
196+
197+
198+ def backwards(self, orm):
199+
200+ # Deleting field 'Meeting.launchpad_blueprint_id'
201+ db.delete_column('schedule_meeting', 'launchpad_blueprint_id')
202+
203+
204+ models = {
205+ 'auth.group': {
206+ 'Meta': {'object_name': 'Group'},
207+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
208+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
209+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
210+ },
211+ 'auth.permission': {
212+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
213+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
214+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
215+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
216+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
217+ },
218+ 'auth.user': {
219+ 'Meta': {'ordering': "['username']", 'object_name': 'User'},
220+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
221+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
222+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
223+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
224+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
225+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
226+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
227+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
228+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
229+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
230+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
231+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
232+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
233+ },
234+ 'contenttypes.contenttype': {
235+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
236+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
237+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
238+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
239+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
240+ },
241+ 'schedule.agenda': {
242+ 'Meta': {'ordering': "('slot', 'room')", 'unique_together': "(('slot', 'room'),)", 'object_name': 'Agenda'},
243+ 'auto': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
244+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
245+ 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Meeting']"}),
246+ 'room': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Room']"}),
247+ 'slot': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Slot']"})
248+ },
249+ 'schedule.attendee': {
250+ 'Meta': {'ordering': "('user__username', 'summit')", 'object_name': 'Attendee'},
251+ 'crew': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_column': "'crew'"}),
252+ 'end_utc': ('django.db.models.fields.DateTimeField', [], {'db_column': "'end'"}),
253+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
254+ 'secret_key_id': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
255+ 'start_utc': ('django.db.models.fields.DateTimeField', [], {'db_column': "'start'"}),
256+ 'summit': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Summit']"}),
257+ 'tracks': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['schedule.Track']", 'symmetrical': 'False', 'blank': 'True'}),
258+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
259+ },
260+ 'schedule.attendeebusy': {
261+ 'Meta': {'ordering': "('attendee', 'start_utc', 'end_utc')", 'object_name': 'AttendeeBusy'},
262+ 'attendee': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'busy_set'", 'to': "orm['schedule.Attendee']"}),
263+ 'end_utc': ('django.db.models.fields.DateTimeField', [], {'db_column': "'end'"}),
264+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
265+ 'start_utc': ('django.db.models.fields.DateTimeField', [], {'db_column': "'start'"})
266+ },
267+ 'schedule.crew': {
268+ 'Meta': {'ordering': "('date_utc', 'attendee')", 'object_name': 'Crew'},
269+ 'attendee': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'crew_schedule'", 'to': "orm['schedule.Attendee']"}),
270+ 'date_utc': ('django.db.models.fields.DateField', [], {'db_column': "'date'"}),
271+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
272+ },
273+ 'schedule.lead': {
274+ 'Meta': {'ordering': "('summit', 'track')", 'object_name': 'Lead'},
275+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
276+ 'lead': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'lead'", 'to': "orm['schedule.Attendee']"}),
277+ 'summit': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Summit']"}),
278+ 'track': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Track']"})
279+ },
280+ 'schedule.meeting': {
281+ 'Meta': {'object_name': 'Meeting'},
282+ 'approved': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '10', 'null': 'True'}),
283+ 'approver': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'approver_set'", 'null': 'True', 'to': "orm['schedule.Attendee']"}),
284+ 'assignee': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'assignee_set'", 'null': 'True', 'to': "orm['schedule.Attendee']"}),
285+ 'description': ('django.db.models.fields.TextField', [], {'max_length': '2047', 'blank': 'True'}),
286+ 'drafter': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'drafter_set'", 'null': 'True', 'to': "orm['schedule.Attendee']"}),
287+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
288+ 'launchpad_blueprint_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
289+ 'name': ('summit.schedule.fields.NameField', [], {'max_length': '100'}),
290+ 'override_break': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
291+ 'pad_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
292+ 'participants': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['schedule.Attendee']", 'symmetrical': 'False', 'through': "orm['schedule.Participant']", 'blank': 'True'}),
293+ 'priority': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
294+ 'private': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
295+ 'private_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
296+ 'requires_dial_in': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
297+ 'scribe': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'scribe_set'", 'null': 'True', 'to': "orm['schedule.Attendee']"}),
298+ 'slots': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
299+ 'spec_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
300+ 'status': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
301+ 'summit': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Summit']"}),
302+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
303+ 'tracks': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['schedule.Track']", 'symmetrical': 'False', 'blank': 'True'}),
304+ 'type': ('django.db.models.fields.CharField', [], {'default': "u'discussion'", 'max_length': '15'}),
305+ 'video': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
306+ 'wiki_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
307+ },
308+ 'schedule.participant': {
309+ 'Meta': {'ordering': "('meeting', 'attendee', 'participation')", 'object_name': 'Participant'},
310+ 'attendee': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Attendee']"}),
311+ 'from_launchpad': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
312+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
313+ 'meeting': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Meeting']"}),
314+ 'participation': ('django.db.models.fields.CharField', [], {'default': "'ATTENDING'", 'max_length': '32', 'null': 'True'})
315+ },
316+ 'schedule.room': {
317+ 'Meta': {'ordering': "('summit', 'name')", 'object_name': 'Room'},
318+ 'end_utc': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_column': "'end'", 'blank': 'True'}),
319+ 'has_dial_in': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
320+ 'icecast_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
321+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
322+ 'irc_channel': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
323+ 'name': ('summit.schedule.fields.NameField', [], {'max_length': '50'}),
324+ 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
325+ 'start_utc': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_column': "'start'", 'blank': 'True'}),
326+ 'summit': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Summit']"}),
327+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
328+ 'tracks': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['schedule.Track']", 'symmetrical': 'False', 'blank': 'True'}),
329+ 'type': ('django.db.models.fields.CharField', [], {'default': "u'open'", 'max_length': '7'})
330+ },
331+ 'schedule.roombusy': {
332+ 'Meta': {'ordering': "('room', 'start_utc', 'end_utc')", 'object_name': 'RoomBusy'},
333+ 'end_utc': ('django.db.models.fields.DateTimeField', [], {'db_column': "'end'"}),
334+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
335+ 'room': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'busy_set'", 'to': "orm['schedule.Room']"}),
336+ 'start_utc': ('django.db.models.fields.DateTimeField', [], {'db_column': "'start'"})
337+ },
338+ 'schedule.slot': {
339+ 'Meta': {'ordering': "('summit', 'start_utc', 'end_utc')", 'object_name': 'Slot'},
340+ 'end_utc': ('django.db.models.fields.DateTimeField', [], {'db_column': "'end'"}),
341+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
342+ 'start_utc': ('django.db.models.fields.DateTimeField', [], {'db_column': "'start'"}),
343+ 'summit': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Summit']"}),
344+ 'type': ('django.db.models.fields.CharField', [], {'default': "u'open'", 'max_length': '7'})
345+ },
346+ 'schedule.summit': {
347+ 'Meta': {'ordering': "('name',)", 'object_name': 'Summit'},
348+ 'date_end': ('django.db.models.fields.DateField', [], {'null': 'True'}),
349+ 'date_start': ('django.db.models.fields.DateField', [], {'null': 'True'}),
350+ 'description': ('django.db.models.fields.TextField', [], {'max_length': '2047', 'blank': 'True'}),
351+ 'etherpad': ('django.db.models.fields.URLField', [], {'default': "'http://pad.ubuntu.com/'", 'max_length': '75'}),
352+ 'hashtag': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}),
353+ 'help_text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
354+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
355+ 'last_update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
356+ 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
357+ 'managers': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'managers'", 'blank': 'True', 'to': "orm['auth.User']"}),
358+ 'name': ('summit.schedule.fields.NameField', [], {'max_length': '50'}),
359+ 'qr': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}),
360+ 'schedulers': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'schedulers'", 'blank': 'True', 'to': "orm['auth.User']"}),
361+ 'sites': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['sites.Site']", 'symmetrical': 'False'}),
362+ 'state': ('django.db.models.fields.CharField', [], {'default': "u'sponsor'", 'max_length': '10'}),
363+ 'timezone': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
364+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'})
365+ },
366+ 'schedule.summitsprint': {
367+ 'Meta': {'ordering': "('summit', 'import_url')", 'object_name': 'SummitSprint'},
368+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
369+ 'import_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
370+ 'summit': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sprint_set'", 'to': "orm['schedule.Summit']"})
371+ },
372+ 'schedule.track': {
373+ 'Meta': {'ordering': "('summit', 'title', 'slug')", 'object_name': 'Track'},
374+ 'allow_adjacent_sessions': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
375+ 'color': ('django.db.models.fields.CharField', [], {'default': "'FFFFFF'", 'max_length': '6'}),
376+ 'description': ('django.db.models.fields.TextField', [], {'max_length': '1000', 'null': 'True'}),
377+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
378+ 'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}),
379+ 'summit': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Summit']"}),
380+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'})
381+ },
382+ 'sites.site': {
383+ 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
384+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
385+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
386+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
387+ }
388+ }
389+
390+ complete_apps = ['schedule']
391
392=== modified file 'summit/schedule/models/meetingmodel.py'
393--- summit/schedule/models/meetingmodel.py 2012-07-14 20:19:27 +0000
394+++ summit/schedule/models/meetingmodel.py 2012-10-03 21:15:28 +0000
395@@ -74,6 +74,7 @@
396 (u'PENDING', u'Pending'),
397 (u'APPROVED', u'Approved'),
398 (u'DECLINED', u'Declined'),
399+ (u'REMOVED', u'Removed'),
400 )
401
402 summit = models.ForeignKey(Summit)
403@@ -118,6 +119,7 @@
404 related_name='scribe_set')
405 participants = models.ManyToManyField(Attendee, blank=True,
406 through='Participant')
407+ launchpad_blueprint_id = models.IntegerField(blank=True, null=True)
408
409 class Meta:
410 app_label = 'schedule'
411@@ -296,6 +298,12 @@
412
413 self.approved = 'APPROVED'
414
415+ name = elem.get("name")
416+ if name:
417+ self.name = name[:100]
418+ else:
419+ self.name = None
420+
421 status = elem.get("status")
422 if status:
423 self.status = status
424
425=== modified file 'summit/schedule/models/summitmodel.py'
426--- summit/schedule/models/summitmodel.py 2012-08-09 15:53:51 +0000
427+++ summit/schedule/models/summitmodel.py 2012-10-03 21:15:28 +0000
428@@ -233,14 +233,16 @@
429 % self.name)]
430 return urls
431
432- def update_from_launchpad_response(self, response):
433+ def update_from_launchpad_response(self, response, options={}):
434 meetings = set()
435- for elem in response.find("attendees").findall("person"):
436- self.update_attendee_from_launchpad(elem)
437- for elem in response.find("unscheduled").findall("meeting"):
438- meeting = self.update_meeting_from_launchpad(elem)
439- if meeting is not None:
440- meetings.add(meeting)
441+ if not options.get('skip_attendees', False):
442+ for elem in response.find("attendees").findall("person"):
443+ self.update_attendee_from_launchpad(elem, options)
444+ if not options.get('skip_meetings', False):
445+ for elem in response.find("unscheduled").findall("meeting"):
446+ meeting = self.update_meeting_from_launchpad(elem, options)
447+ if meeting is not None:
448+ meetings.add(meeting)
449 return meetings
450
451 def _get_sprint_info_from_launchpad(self, url):
452@@ -264,26 +266,33 @@
453 sprint_info = ElementTree.parse(export)
454 return sprint_info
455
456- def update_from_launchpad(self):
457+ def update_from_launchpad(self, options={}):
458 """Update from Launchpad data."""
459 in_lp = set()
460 urls = self.launchpad_sprint_import_urls()
461 for url in urls:
462 print "Importing from %s" % url
463 sprint_info = self._get_sprint_info_from_launchpad(url)
464- in_lp |= self.update_from_launchpad_response(sprint_info)
465-
466+ in_lp |= self.update_from_launchpad_response(sprint_info, options)
467+
468+ in_db = set(m for m in self.meeting_set.exclude(launchpad_blueprint_id__isnull=True))
469+
470+ for extra in in_db.difference(in_lp):
471+ if not len(extra.agenda_set.all()):
472+ print "will delete %s" % extra.name
473+ extra.approved='REMOVED'
474+ extra.save()
475 self.last_update = datetime.utcnow()
476 self.save()
477
478- def update_attendee_from_launchpad(self, elem):
479+ def update_attendee_from_launchpad(self, elem, options={}):
480 """Update or create single attendee from Launchpad data."""
481+
482 username = elem.get("name", "")
483 if not username:
484 return
485
486 print "user %s" % username
487-
488 try:
489 attendee = self.attendee_set.get(user__username__exact=username[:30])
490 except ObjectDoesNotExist:
491@@ -298,10 +307,15 @@
492 start=datetime.utcnow(),
493 end=datetime.utcnow())
494
495+
496 attendee.update_from_launchpad(elem)
497
498- def update_meeting_from_launchpad(self, elem):
499+ def update_meeting_from_launchpad(self, elem, options={}):
500 """Update or create single meeting from Launchpad data."""
501+ bp_id = elem.get("id", None)
502+ if not bp_id:
503+ return
504+
505 full_name = elem.get("name", "")
506 if not full_name:
507 return
508@@ -309,10 +323,13 @@
509
510 print "meeting %s" % name
511 meeting = ""
512+
513+ slot_length = options.get('slots', 1)
514+
515 try:
516- meeting = self.meeting_set.get(name__exact=name)
517+ meeting = self.meeting_set.get(launchpad_blueprint_id=bp_id)
518 except ObjectDoesNotExist:
519- meeting = self.meeting_set.create(name=name, title=full_name[:100])
520+ meeting = self.meeting_set.create(name=name, title=full_name[:100], slots=slot_length, launchpad_blueprint_id=bp_id)
521 except:
522 pass
523
524
525=== modified file 'summit/schedule/tests.py'
526--- summit/schedule/tests.py 2012-09-09 21:15:17 +0000
527+++ summit/schedule/tests.py 2012-10-03 21:15:28 +0000
528@@ -1667,7 +1667,7 @@
529
530 def test_update_meeting_trims_name(self):
531 summit = factory.make_one(Summit)
532- elem = LaunchpadExportNode(name="very " * 20 + "longname")
533+ elem = LaunchpadExportNode(name="very " * 20 + "longname", id="42")
534 meeting = summit.update_meeting_from_launchpad(elem)
535 # Names are truncated at 100 chars.
536 expected_name = "very " * 20
537@@ -1678,7 +1678,7 @@
538 summit = factory.make_one(Summit)
539 name = "meeting-name"
540 title = "other-title"
541- elem = LaunchpadExportNode(name=name)
542+ elem = LaunchpadExportNode(name=name, id="42")
543 summit.meeting_set.create(name=name, title=title)
544 meeting = summit.update_meeting_from_launchpad(elem)
545 self.assertEqual(name, meeting.name)
546@@ -1695,7 +1695,7 @@
547 def test_update_from_launchpad_response_handles_no_name(self):
548 summit = factory.make_one(Summit)
549 elem = self.get_basic_launchpad_response()
550- meeting_node = LaunchpadExportNode(name=None)
551+ meeting_node = LaunchpadExportNode(name=None, id="42")
552 elem.find("unscheduled").add_child("meeting", meeting_node)
553 meetings = summit.update_from_launchpad_response(elem)
554 self.assertEqual(set(), meetings)
555@@ -1738,16 +1738,30 @@
556 summit = factory.make_one(Summit)
557 def get_sprint_info(url):
558 elem = self.get_basic_launchpad_response()
559- meeting_node = LaunchpadExportNode(name="foo")
560+ meeting_node = LaunchpadExportNode(name="foo", id="42")
561 elem.find("unscheduled").add_child("meeting", meeting_node)
562 return elem
563 summit._get_sprint_info_from_launchpad = get_sprint_info
564 summit.update_from_launchpad()
565 self.assertEqual(1, summit.meeting_set.all().count())
566
567+ def test_update_from_launchpad_does_renames(self):
568+ summit = factory.make_one(Summit)
569+ meeting = summit.meeting_set.create(name="name", launchpad_blueprint_id="42")
570+ def get_sprint_info(url):
571+ elem = self.get_basic_launchpad_response()
572+ meeting_node = LaunchpadExportNode(name="other", id="42")
573+ elem.find("unscheduled").add_child("meeting", meeting_node)
574+ return elem
575+ summit._get_sprint_info_from_launchpad = get_sprint_info
576+ summit.update_from_launchpad()
577+ # Since both had blueprint id 42, it should just update the existing meeting
578+ self.assertEqual(0, summit.meeting_set.filter(name__exact="name").count())
579+ self.assertEqual(1, summit.meeting_set.filter(name__exact="other").count())
580+
581 def test_update_from_launchpad_deletes_unseen_meetings(self):
582 summit = factory.make_one(Summit)
583- meeting = summit.meeting_set.create(spec_url='test_url', name="name")
584+ meeting = summit.meeting_set.create(spec_url='test_url', name="name", launchpad_blueprint_id="42")
585 def get_sprint_info(url):
586 elem = self.get_basic_launchpad_response()
587 meeting_node = LaunchpadExportNode(name="other")
588@@ -1755,14 +1769,27 @@
589 return elem
590 summit._get_sprint_info_from_launchpad = get_sprint_info
591 summit.update_from_launchpad()
592- self.assertEqual(0, summit.meeting_set.filter(name__exact="name").count())
593+ self.assertEqual(1, summit.meeting_set.filter(name__exact="name").count())
594+ self.assertEqual(0, summit.meeting_set.filter(name__exact="name").exclude(approved='REMOVED').count())
595+
596+ def test_update_from_launchpad_doesnt_delete_meetings_with_spec_url(self):
597+ summit = factory.make_one(Summit)
598+ meeting = summit.meeting_set.create(spec_url='http://example.com/foo', name="name", launchpad_blueprint_id="42")
599+ def get_sprint_info(url):
600+ elem = self.get_basic_launchpad_response()
601+ meeting_node = LaunchpadExportNode(name="other", id="43")
602+ elem.find("unscheduled").add_child("meeting", meeting_node)
603+ return elem
604+ summit._get_sprint_info_from_launchpad = get_sprint_info
605+ summit.update_from_launchpad()
606+ self.assertEqual(1, summit.meeting_set.filter(name__exact="name").count())
607
608 def test_update_from_launchpad_doesnt_delete_meetings_with_no_spec_url(self):
609 summit = factory.make_one(Summit)
610- meeting = summit.meeting_set.create(spec_url='', name="name")
611+ meeting = summit.meeting_set.create(spec_url='', name="name", launchpad_blueprint_id="42")
612 def get_sprint_info(url):
613 elem = self.get_basic_launchpad_response()
614- meeting_node = LaunchpadExportNode(name="other")
615+ meeting_node = LaunchpadExportNode(name="other", id="43")
616 elem.find("unscheduled").add_child("meeting", meeting_node)
617 return elem
618 summit._get_sprint_info_from_launchpad = get_sprint_info

Subscribers

People subscribed via source and target branches

to all changes: