Merge lp:~mhall119/loco-team-portal/686268 into lp:loco-team-portal

Proposed by Michael Hall
Status: Merged
Approved by: Chris Johnston
Approved revision: 369
Merged at revision: 369
Proposed branch: lp:~mhall119/loco-team-portal/686268
Merge into: lp:loco-team-portal
Diff against target: 718 lines (+469/-33)
14 files modified
loco_directory/common/views.py (+10/-0)
loco_directory/media/css/newstyle.css (+26/-0)
loco_directory/meetings/forms.py (+49/-17)
loco_directory/meetings/models.py (+24/-6)
loco_directory/meetings/templatetags/recurse.py (+82/-0)
loco_directory/meetings/urls.py (+3/-0)
loco_directory/meetings/views.py (+119/-4)
loco_directory/services/urls.py (+1/-0)
loco_directory/services/views.py (+4/-1)
loco_directory/templates/meetings/agenda_item_delete_confirm.html (+43/-0)
loco_directory/templates/meetings/agenda_item_new.html (+36/-0)
loco_directory/templates/meetings/agenda_item_update.html (+37/-0)
loco_directory/templates/meetings/team_meeting_detail_agenda.inc.html (+19/-5)
loco_directory/templates/site_search.html (+16/-0)
To merge this branch: bzr merge lp:~mhall119/loco-team-portal/686268
Reviewer Review Type Date Requested Status
Chris Johnston Needs Fixing
Review via email: mp+47162@code.launchpad.net

Description of the change

Added forms for adding/updating agenda items, as well as a template tag for recursively displaying them, and css to make it all look nice.

To post a comment you must log in.
Revision history for this message
Dave Walker (davewalker) wrote :

Visual review looks good, but does it not require a migration script for the model changes?

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

The migration script was part of a previous merge, this is just adding a front-end to it

lp:~mhall119/loco-team-portal/686268 updated
366. By Chris Johnston

Fixes bug 639772. Props mhall119

Revision history for this message
Chris Johnston (cjohnston) wrote :

IMO, the owner should be assigned automatically.

The time still shows up as "13:53:09.032017" - it really only needs HH:MM

Can we have a mouseover on the agenda item link say something like "Update <agenda item>" (i.e. when you hover over "Agenda item 1" in: Agenda item 1 - Chris Johnston @ 2011-01-23 13:53 it would read "Update Agenda item 1")

What do you think about indenting sub items a little more?

I also think that there should be some sort of end (if there isn't already, I've gone down 4 levels) to the subitems.

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

The owner is defaulted to the logged in user, but it's changeable. There have been times were I've added an item for someone else, or someone else has added one for me.

Agreed on the time, I'll fix that.

How much more indentation do you think it needs?

It would be more work to limit the depth of the tree than it would be to leave it up to the user. Anything over 3 levels deep will only get a point bullet though, rather than a number or letter.

lp:~mhall119/loco-team-portal/686268 updated
367. By Michael Hall

Show appropriate timezone and localtimes on events and meetings, merge from Chris Johnston

368. By Michael Hall

Add link to meeting chair's lp profile, merge from Chris Johnston

369. By Michael Hall

Merge from trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'loco_directory/common/views.py'
--- loco_directory/common/views.py 2010-11-30 12:54:39 +0000
+++ loco_directory/common/views.py 2011-01-24 02:52:15 +0000
@@ -68,6 +68,7 @@
68 global_events = []68 global_events = []
69 team_events = []69 team_events = []
70 venues = []70 venues = []
71 meetings = []
71 q = None72 q = None
72 form = SiteSearchForm(data=request.GET)73 form = SiteSearchForm(data=request.GET)
73 if form.is_valid():74 if form.is_valid():
@@ -77,11 +78,13 @@
77 global_events = search_global_events(q)78 global_events = search_global_events(q)
78 team_events = search_team_events(q)79 team_events = search_team_events(q)
79 venues = search_venues(q)80 venues = search_venues(q)
81 meetings = search_meetings(q)
80 context = {82 context = {
81 'teams': teams,83 'teams': teams,
82 'global_events': global_events,84 'global_events': global_events,
83 'team_events': team_events,85 'team_events': team_events,
84 'venues': venues,86 'venues': venues,
87 'meetings': meetings,
85 'q': q,88 'q': q,
86 'colcycle' : simple_iterator('col_left', 'col_right'),89 'colcycle' : simple_iterator('col_left', 'col_right'),
87 }90 }
@@ -114,5 +117,12 @@
114 venue_list = Venue.objects.filter(Q(name__icontains=q) | Q(country__name__icontains=q) | Q(city__icontains=q) | Q(address__icontains=q)).order_by('name').distinct()117 venue_list = Venue.objects.filter(Q(name__icontains=q) | Q(country__name__icontains=q) | Q(city__icontains=q) | Q(address__icontains=q)).order_by('name').distinct()
115 return venue_list118 return venue_list
116 119
120def search_meetings(q):
121 from meetings.models import TeamMeeting
122 from django.db.models import Q
123 meeting_list = TeamMeeting.objects.next_meetings()
124 meeting_list = meeting_list.filter(Q(name__icontains=q) | Q(teams__name__icontains=q) | Q(agenda__title__icontains=q)).distinct()
125 return meeting_list
126
117 127
118128
119129
=== modified file 'loco_directory/media/css/newstyle.css'
--- loco_directory/media/css/newstyle.css 2011-01-02 18:45:45 +0000
+++ loco_directory/media/css/newstyle.css 2011-01-24 02:52:15 +0000
@@ -434,3 +434,29 @@
434.attendee-mugshot {434.attendee-mugshot {
435 vertical-align: middle;435 vertical-align: middle;
436}436}
437
438.agenda-list {
439 list-style-type: decimal;
440}
441
442.agenda-list .agenda-list {
443 margin-left: 20px;
444 list-style-type: lower-alpha;
445}
446
447.agenda-list .agenda-list .agenda-list {
448 list-style-type: lower-roman;
449}
450
451.agenda-list .agenda-list .agenda-list .agenda-list {
452 list-style-type: circle;
453}
454
455.agenda-title {
456 font-weight: bold;
457}
458
459.agenda-description {
460 margin-left: 30px;
461 font-size: 0.9em;
462}
437463
=== modified file 'loco_directory/meetings/forms.py'
--- loco_directory/meetings/forms.py 2011-01-24 02:44:41 +0000
+++ loco_directory/meetings/forms.py 2011-01-24 02:52:15 +0000
@@ -4,13 +4,23 @@
4from django.utils.translation import ugettext as _4from django.utils.translation import ugettext as _
5from django.core.urlresolvers import reverse5from django.core.urlresolvers import reverse
66
7from models import BaseMeeting, TeamMeeting7from models import BaseMeeting, TeamMeeting, AgendaItem
8from common.forms import RenderableMixin8from common.forms import RenderableMixin
9from userprofiles.models import UserProfile9from userprofiles.models import UserProfile
1010
11import pytz11import pytz
12import urllib12import urllib
1313
14def grouped_user_list(teams):
15 other_members, team_members = [], []
16 for profile in UserProfile.objects.filter(user__groups__name__in=teams):
17 team_members.append((profile.id, str(profile)))
18 for profile in UserProfile.objects.all().exclude(pk__in=[m[0] for m in team_members]):
19 other_members.append((profile.id, str(profile)))
20
21 return [('', '---------'),
22 (_('Team members'), team_members),
23 (_('Other users'), other_members)]
1424
15class BaseMeetingForm(forms.ModelForm, RenderableMixin):25class BaseMeetingForm(forms.ModelForm, RenderableMixin):
16 """ 26 """
@@ -60,22 +70,10 @@
60 def __init__(self, teams=None, *args, **kargs):70 def __init__(self, teams=None, *args, **kargs):
61 super(TeamMeetingForm, self).__init__(*args, **kargs)71 super(TeamMeetingForm, self).__init__(*args, **kargs)
62 if teams:72 if teams:
63 self.fields['chair'].choices = self.grouped_user_list(teams)73 self.fields['chair'].choices = grouped_user_list(teams)
64 self.fields['channel'].initial = teams[0].irc_chan74 elif self.instance.teams:
65 elif self.instance:75 self.fields['chair'].choices = grouped_user_list([team.lp_name for team in self.instance.teams.iterator()])
66 self.fields['chair'].choices = self.grouped_user_list(self.instance.teams.iterator())
67 76
68 def grouped_user_list(self, teams):
69 print dir(teams)
70 other_members, team_members = [], []
71 for profile in UserProfile.objects.filter(user__groups__name__in=teams):
72 team_members.append((profile.id, str(profile)))
73 for profile in UserProfile.objects.all().exclude(user__groups__name__in=teams):
74 other_members.append((profile.id, str(profile)))
75 return [('', '---------'),
76 (_('Team members'), team_members),
77 (_('Other users'), other_members)]
78
79 def save(self):77 def save(self):
80 start_date = self.cleaned_data['date_begin']78 start_date = self.cleaned_data['date_begin']
81 self.instance.logs = 'http://irclogs.ubuntu.com/%(date)s/%(channel)s.html#t%(time)s' % {'date': start_date.strftime('%Y/%m/%d'),79 self.instance.logs = 'http://irclogs.ubuntu.com/%(date)s/%(channel)s.html#t%(time)s' % {'date': start_date.strftime('%Y/%m/%d'),
@@ -83,4 +81,38 @@
83 'time': start_date.strftime('%H:%M')}81 'time': start_date.strftime('%H:%M')}
84 return super(TeamMeetingForm, self).save()82 return super(TeamMeetingForm, self).save()
85 83
86 84class AgendaItemForm(forms.ModelForm, RenderableMixin):
85
86 class Meta:
87 model = AgendaItem
88 exclude = ('meeting','created_date')
89
90 def __init__(self, *args, **kargs):
91 super(AgendaItemForm, self).__init__(*args, **kargs)
92 parent_choices = AgendaItem.objects.filter(meeting=self.instance.meeting).exclude(pk=self.instance.id)
93 self.fields['parent'].choices = [('', '')]+[(item.id, unicode(item)) for item in parent_choices if item not in self.instance.descendents]
94 if self.instance:
95 meeting = self.instance.meeting.teammeeting
96 self.fields['owner'].choices = grouped_user_list(meeting.teams.iterator())
97
98
99class AgendaItemFormSet(forms.models.BaseInlineFormSet):
100
101 def __init__(self, *args, **kargs):
102 super(AgendaItemFormSet, self).__init__(*args, **kargs)
103 self.node_tree = {}
104
105 def add_fields(self, form, index):
106 super(AgendaItemFormSet, self).add_fields(form, index)
107 self.fields['node_id'] = IntegerField(label=_(u'Node'),
108 initial=index,
109 required=False)
110 self.node_tree[form.instance.id] = index
111 self.fields['parent_node'] = IntegerField(label=_(u'Parent Node'),
112 initial=self.node_tree.get(form.instance.parent, None),
113 required=False)
114
115 def save(self):
116 pass
117 def as_tree(self):
118 pass
87119
=== modified file 'loco_directory/meetings/models.py'
--- loco_directory/meetings/models.py 2011-01-10 16:08:59 +0000
+++ loco_directory/meetings/models.py 2011-01-24 02:52:15 +0000
@@ -92,6 +92,9 @@
92 92
93class AgendaItemManager(models.Manager):93class AgendaItemManager(models.Manager):
9494
95 def top(self):
96 return self.filter(parent__isnull=True).order_by('order')
97
95 def as_tree(self):98 def as_tree(self):
96 cache = {}99 cache = {}
97 tree = []100 tree = []
@@ -109,27 +112,42 @@
109class AgendaItem(models.Model):112class AgendaItem(models.Model):
110113
111 class Meta:114 class Meta:
112 ordering = ('parent__id', 'order')115 ordering = ('parent__id', 'order', 'created_date')
113 116
114 meeting = models.ForeignKey(BaseMeeting, verbose_name=_('Meeting'), related_name='agenda', help_text=_('meeting during which this agenda item is to be discussed'))117 meeting = models.ForeignKey(BaseMeeting, verbose_name=_('Meeting'), related_name='agenda', help_text=_('meeting during which this agenda item is to be discussed'))
115 parent = models.ForeignKey('self', verbose_name=_('Parent Agenda Item'), related_name='children', help_text=_('agenda item that contains this item'), blank=True, null=True)118 title = models.CharField(verbose_name=_('Title'), max_length = 150, help_text=_('descriptive name for this item'))
116 order = models.PositiveIntegerField(verbose_name=_('Order'), help_text=_('index number of where this item falls in the agenda'))
117 owner = models.ForeignKey(UserProfile, verbose_name=_('Owner'), help_text=_('person proposing or responsible for this item'))119 owner = models.ForeignKey(UserProfile, verbose_name=_('Owner'), help_text=_('person proposing or responsible for this item'))
118 created_date = models.DateTimeField(verbose_name=_('Created Date'), auto_now_add=True, help_text=_('timestamp of when this item was created'))120 created_date = models.DateTimeField(verbose_name=_('Created Date'), auto_now_add=True, help_text=_('timestamp of when this item was created'))
119 title = models.CharField(verbose_name=_('Title'), max_length = 150, help_text=_('descriptive name for this item'))
120 description = models.TextField(verbose_name=_('Description'), help_text=_('detailed description of this item'), blank=True, null=True)121 description = models.TextField(verbose_name=_('Description'), help_text=_('detailed description of this item'), blank=True, null=True)
122 parent = models.ForeignKey('self', verbose_name=_('Parent Agenda Item'), related_name='children', help_text=_('agenda item that contains this item'), blank=True, null=True)
123 order = models.PositiveIntegerField(verbose_name=_('Order'), help_text=_('index number of where this item falls in the agenda'), default=1)
121 log = models.URLField(verbose_name=_('Log URL'), max_length=200, verify_exists=False, help_text=_('URL to this item\'s discussion'), blank=True, null=True)124 log = models.URLField(verbose_name=_('Log URL'), max_length=200, verify_exists=False, help_text=_('URL to this item\'s discussion'), blank=True, null=True)
122 125
123 objects = AgendaItemManager()126 objects = AgendaItemManager()
124 127
128 def get_descendents(self):
129 descendents = []
130 if self.id is None:
131 return descendents
132 for child in self.children.all():
133 descendents.append(child)
134 descendents.extend(child.descendents)
135 return descendents
136 descendents = property(get_descendents)
137
125 def get_sig(self):138 def get_sig(self):
126 return '<a href="http://launchpad.net/~%s">%s</a> %s' % (self.owner.user.username, self.owner.realname, self.created_date)139 return '<a href="http://launchpad.net/~%s" target="launchpaduser">%s</a> %s' % (self.owner.user.username, self.owner.realname, self.created_date)
127 140
128 sig = property(get_sig)141 sig = property(get_sig)
129 142
143 def save(self, *args, **kargs):
144 if not self.created_date:
145 self.created_date = datetime.datetime.now()
146 return super(AgendaItem, self).save(*args, **kargs)
147
130 def __unicode__(self):148 def __unicode__(self):
131 if self.parent is None:149 if self.parent is None:
132 return '%s: %s' % (self.meeting, self.title)150 return '%s' % self.title
133 else:151 else:
134 return '%s->%s' % (self.parent, self.title)152 return '%s->%s' % (self.parent, self.title)
135 153
136154
=== added directory 'loco_directory/meetings/templatetags'
=== added file 'loco_directory/meetings/templatetags/__init__.py'
=== added file 'loco_directory/meetings/templatetags/recurse.py'
--- loco_directory/meetings/templatetags/recurse.py 1970-01-01 00:00:00 +0000
+++ loco_directory/meetings/templatetags/recurse.py 2011-01-24 02:52:15 +0000
@@ -0,0 +1,82 @@
1###############################################################################
2# Recurse template tag for Django v1.1
3# Copyright (C) 2008 Lucas Murray
4# http://www.undefinedfire.com
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU Lesser General Public License as published
8# by the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU Lesser General Public License for more details.
15###############################################################################
16
17from django import template
18
19register = template.Library()
20
21class RecurseNode(template.Node):
22 def __init__(self, var, name, child, nodeList):
23 self.var = var
24 self.name = name
25 self.child = child
26 self.nodeList = nodeList
27
28 def __repr__(self):
29 return '<RecurseNode>'
30
31 def renderCallback(self, context, vals, level):
32 output = []
33 try:
34 if len(vals):
35 pass
36 except:
37 vals = [vals]
38 if len(vals):
39 if 'loop' in self.nodeList:
40 output.append(self.nodeList['loop'].render(context))
41 for val in vals:
42 context.push()
43 context['level'] = level
44 context[self.name] = val
45 if 'child' in self.nodeList:
46 output.append(self.nodeList['child'].render(context))
47 child = self.child.resolve(context)
48 if child:
49 output.append(self.renderCallback(context, child, level + 1))
50 if 'endloop' in self.nodeList:
51 output.append(self.nodeList['endloop'].render(context))
52 else:
53 output.append(self.nodeList['endrecurse'].render(context))
54 context.pop()
55 if 'endloop' in self.nodeList:
56 output.append(self.nodeList['endrecurse'].render(context))
57 return ''.join(output)
58
59 def render(self, context):
60 vals = self.var.resolve(context)
61 output = self.renderCallback(context, vals, 1)
62 return output
63
64def do_recurse(parser, token):
65 bits = list(token.split_contents())
66 if len(bits) != 6 and bits[2] != 'with' and bits[4] != 'as':
67 raise template.TemplateSyntaxError, "Invalid tag syxtax expected '{% recurse [childVar] with [parents] as [parent] %}'"
68 child = parser.compile_filter(bits[1])
69 var = parser.compile_filter(bits[3])
70 name = bits[5]
71
72 nodeList = {}
73 while len(nodeList) < 4:
74 temp = parser.parse(('child','loop','endloop','endrecurse'))
75 tag = parser.tokens[0].contents
76 nodeList[tag] = temp
77 parser.delete_first_token()
78 if tag == 'endrecurse':
79 break
80
81 return RecurseNode(var, name, child, nodeList)
82do_recurse = register.tag('recurse', do_recurse)
0\ No newline at end of file83\ No newline at end of file
184
=== modified file 'loco_directory/meetings/urls.py'
--- loco_directory/meetings/urls.py 2010-12-02 09:12:53 +0000
+++ loco_directory/meetings/urls.py 2011-01-24 02:52:15 +0000
@@ -16,4 +16,7 @@
16 url(r'^team/(?P<team_slug>[a-zA-Z0-9\-\.\+?]+)/ical/$', 'meetings.views.team_meeting_list_ical', name='team-meeting-list-ical'),16 url(r'^team/(?P<team_slug>[a-zA-Z0-9\-\.\+?]+)/ical/$', 'meetings.views.team_meeting_list_ical', name='team-meeting-list-ical'),
17 url(r'^team/add/$', 'meetings.views.team_meeting_select', name='team-meeting-select'),17 url(r'^team/add/$', 'meetings.views.team_meeting_select', name='team-meeting-select'),
1818
19 url(r'^team/(?P<team_meeting_id>\d+)/agenda/(?P<agenda_item_id>\d+)/delete/$', 'meetings.views.agenda_item_delete', name='agenda-item-delete'),
20 url(r'^team/(?P<team_meeting_id>\d+)/agenda/(?P<agenda_item_id>\d+)/update/$', 'meetings.views.agenda_item_update', name='agenda-item-update'),
21 url(r'^team/(?P<team_meeting_id>\d+)/agenda/add/$', 'meetings.views.agenda_item_new', name='agenda-item-new'),
19)22)
2023
=== modified file 'loco_directory/meetings/views.py'
--- loco_directory/meetings/views.py 2011-01-18 20:44:47 +0000
+++ loco_directory/meetings/views.py 2011-01-24 02:52:15 +0000
@@ -6,15 +6,16 @@
6from django.utils.translation import ugettext as _6from django.utils.translation import ugettext as _
7from django.core.urlresolvers import reverse7from django.core.urlresolvers import reverse
88
9from meetings.models import TeamMeeting9from meetings.models import TeamMeeting, AgendaItem
10from teams.models import Team10from teams.models import Team
1111
12from forms import TeamMeetingForm12from forms import TeamMeetingForm, AgendaItemForm
13from django.db.models import Q13from django.db.models import Q
1414
15from common.utils import redirect, simple_iterator15from common.utils import redirect, simple_iterator
16from common import launchpad16from common import launchpad
1717
18from userprofiles.models import UserProfile
18import datetime19import datetime
1920
20def meeting_list(request):21def meeting_list(request):
@@ -172,16 +173,18 @@
172 is_on_lc = launchpad.is_user_on_loco_council(request.user)173 is_on_lc = launchpad.is_user_on_loco_council(request.user)
173 is_member = launchpad.is_team_member(request.user, team_object)174 is_member = launchpad.is_team_member(request.user, team_object)
174 175
176 team_meeting_object = TeamMeeting(chair=team_object.owner_profile,
177 channel=team_object.irc_chan)
175 if is_on_lc or is_member:178 if is_on_lc or is_member:
176 if request.method == 'POST':179 if request.method == 'POST':
177 form = TeamMeetingForm(data=request.POST, teams=[team_object])180 form = TeamMeetingForm(data=request.POST, teams=[team_object], instance=team_meeting_object)
178 if form.is_valid():181 if form.is_valid():
179 team_meeting = form.save()182 team_meeting = form.save()
180 team_meeting.teams.add(team_object)183 team_meeting.teams.add(team_object)
181 team_meeting_id = team_meeting.id 184 team_meeting_id = team_meeting.id
182 return HttpResponseRedirect(reverse('team-meeting-detail', kwargs={'team_meeting_id': team_meeting_id}))185 return HttpResponseRedirect(reverse('team-meeting-detail', kwargs={'team_meeting_id': team_meeting_id}))
183 else:186 else:
184 form = TeamMeetingForm(teams=[team_object])187 form = TeamMeetingForm(teams=[team_object], instance=team_meeting_object)
185 188
186 context = {189 context = {
187 'team_object': team_object,190 'team_object': team_object,
@@ -262,3 +265,115 @@
262 else:265 else:
263 request.user.message_set.create(message=_('You can not update this team meeting. You are not member of the team or on the LoCo Council.'))266 request.user.message_set.create(message=_('You can not update this team meeting. You are not member of the team or on the LoCo Council.'))
264 return redirect( team_meeting_object )267 return redirect( team_meeting_object )
268
269@login_required
270def agenda_item_new(request, team_meeting_id):
271 """
272 new agenda item
273 """
274 team_meeting_object = get_object_or_404(TeamMeeting, pk=team_meeting_id)
275 try:
276 user = UserProfile.objects.get(user=request.user)
277 agenda_item_object = AgendaItem(meeting=team_meeting_object,
278 owner=user,
279 created_date=datetime.datetime.now())
280 except UserProfile.DoesNotExist:
281 agenda_item_object = AgendaItem(meeting=team_meeting_object,
282 created_date=datetime.datetime.now())
283 is_member = False
284 for team in team_meeting_object.teams.all():
285 if launchpad.is_team_member(request.user, team):
286 is_member = True
287 break
288 is_on_lc = launchpad.is_user_on_loco_council(request.user)
289
290 if is_on_lc or is_member:
291 if request.method == 'POST':
292 form = AgendaItemForm(data=request.POST, instance=agenda_item_object)
293 if form.is_valid():
294 agenda_item_object = form.save()
295 request.user.message_set.create(message=_('Meeting agenda updated.'))
296 return redirect( team_meeting_object )
297 else:
298 form = AgendaItemForm(instance=agenda_item_object)
299
300 context = {
301 'team_meeting_object': team_meeting_object,
302 'form': form,
303 }
304 return render_to_response('meetings/agenda_item_new.html',
305 context, RequestContext(request))
306 else:
307 # XXX: Once we move to a new ACL system, this needs fixing.
308 request.user.message_set.create(message=_('You can not add a new agenda item for this team meeting. You are not member of the team or on the LoCo Council.'))
309 return redirect( team_meeting_object )
310
311@login_required
312def agenda_item_update(request, team_meeting_id, agenda_item_id):
313 """
314 update agenda item
315 """
316 team_meeting_object = get_object_or_404(TeamMeeting, pk=team_meeting_id)
317 agenda_item_object = get_object_or_404(AgendaItem, pk=agenda_item_id)
318 #check if user is admin or owner of a team
319 is_member = False
320 for team in team_meeting_object.teams.all():
321 if launchpad.is_team_member(request.user, team):
322 is_member = True
323 break
324
325 is_on_lc = launchpad.is_user_on_loco_council(request.user)
326
327 if is_on_lc or is_member:
328 if request.method == 'POST':
329 form = AgendaItemForm(data=request.POST, instance=agenda_item_object)
330 if form.is_valid():
331 form.save()
332 request.user.message_set.create(message=_('Meeting agenda updated.'))
333 return redirect( team_meeting_object )
334 else:
335 form = AgendaItemForm(instance=agenda_item_object)
336
337 context = {
338 'team_meeting_object': team_meeting_object,
339 'agenda_item_object': agenda_item_object,
340 'form': form,
341 }
342 return render_to_response('meetings/agenda_item_update.html',
343 context, RequestContext(request))
344 else:
345 request.user.message_set.create(message=_('You can not update this team meeting agenda. You are not member of the team or on the LoCo Council.'))
346 return redirect( team_meeting_object )
347
348@login_required
349def agenda_item_delete(request, team_meeting_id, agenda_item_id):
350 """
351 delete an agenda item
352 """
353 team_meeting_object = get_object_or_404(TeamMeeting, pk=team_meeting_id)
354 agenda_item_object = get_object_or_404(AgendaItem, pk=agenda_item_id)
355 #check if user is admin or owner of a team
356 is_member = False
357 for team in team_meeting_object.teams.all():
358 if launchpad.is_team_member(request.user, team):
359 is_member = True
360 break
361
362 is_on_lc = launchpad.is_user_on_loco_council(request.user)
363
364 if is_on_lc or is_member:
365 if request.method == 'POST':
366 agenda_item_object.delete()
367 request.user.message_set.create(message=_('Agenda Item removed.'))
368 return redirect( team_meeting_object )
369 else:
370 context = {
371 'team_meeting_object': team_meeting_object,
372 'agenda_item_object': agenda_item_object}
373 return render_to_response('meetings/agenda_item_delete_confirm.html', context, RequestContext(request))
374
375 else:
376 request.user.message_set.create(message=_('You can not remove this agenda item. You are not admin/owner of the Launchpad team or on the LoCo Council.'))
377 return redirect( team_meeting_object )
378
379
265380
=== modified file 'loco_directory/services/urls.py'
--- loco_directory/services/urls.py 2010-12-02 07:34:24 +0000
+++ loco_directory/services/urls.py 2011-01-24 02:52:15 +0000
@@ -12,6 +12,7 @@
12 url(r'^continents/(.*)$', 'services.views.continent_service', name='continent_service'),12 url(r'^continents/(.*)$', 'services.views.continent_service', name='continent_service'),
13 url(r'^events/(.*)$', 'services.views.team_event_service', name='team_event_service'),13 url(r'^events/(.*)$', 'services.views.team_event_service', name='team_event_service'),
14 url(r'^meeting/(.*)$', 'services.views.meeting_service', name='meeting_service'),14 url(r'^meeting/(.*)$', 'services.views.meeting_service', name='meeting_service'),
15 url(r'^agenda/(.*)$', 'services.views.meeting_agenda_service', name='meeting_agenda_service'),
15 url(r'^global/(.*)$', 'services.views.global_event_service', name='global_event_service'),16 url(r'^global/(.*)$', 'services.views.global_event_service', name='global_event_service'),
16 url(r'^comments/(.*)$', 'services.views.event_comment_service', name='event_comment_service'),17 url(r'^comments/(.*)$', 'services.views.event_comment_service', name='event_comment_service'),
17 url(r'^attendees/(.*)$', 'services.views.event_attendee_service', name='event_attendee_service'),18 url(r'^attendees/(.*)$', 'services.views.event_attendee_service', name='event_attendee_service'),
1819
=== modified file 'loco_directory/services/views.py'
--- loco_directory/services/views.py 2010-12-19 19:20:44 +0000
+++ loco_directory/services/views.py 2011-01-24 02:52:15 +0000
@@ -1,6 +1,6 @@
1from teams.models import Team, Continent, Country, Language1from teams.models import Team, Continent, Country, Language
2from events.models import GlobalEvent, TeamEvent, TeamEventComment, Attendee2from events.models import GlobalEvent, TeamEvent, TeamEventComment, Attendee
3from meetings.models import TeamMeeting3from meetings.models import TeamMeeting, AgendaItem
4from venues.models import Venue4from venues.models import Venue
5from userprofiles.models import UserProfile5from userprofiles.models import UserProfile
6from django.contrib.auth.models import User, Group6from django.contrib.auth.models import User, Group
@@ -22,6 +22,9 @@
22def meeting_service(request, url):22def meeting_service(request, url):
23 return model_service(TeamMeeting, request, url)23 return model_service(TeamMeeting, request, url)
24 24
25def meeting_agenda_service(request, url):
26 return model_service(AgendaItem, request, url)
27
25def global_event_service(request, url):28def global_event_service(request, url):
26 return model_service(GlobalEvent, request, url)29 return model_service(GlobalEvent, request, url)
2730
2831
=== added file 'loco_directory/templates/meetings/agenda_item_delete_confirm.html'
--- loco_directory/templates/meetings/agenda_item_delete_confirm.html 1970-01-01 00:00:00 +0000
+++ loco_directory/templates/meetings/agenda_item_delete_confirm.html 2011-01-24 02:52:15 +0000
@@ -0,0 +1,43 @@
1{% extends "base.html" %}
2{% load i18n %}
3{% load recurse %}
4
5{% block title %}{% trans "Delete Agenda Item" %} | {% trans "Ubuntu LoCo Team Directory" %} {% endblock %}
6
7{% block sub_nav_links %}
8<a class="sub-nav-item" href="{% url team-meeting-detail team_meeting_object.id %}">{% trans "Back to Meeting Details" %}</a>
9{% endblock %}
10
11{% block extrahead %}{{ block.super }}
12{{form.media}}
13{% endblock %}
14
15{% block content %}
16<article class="main-content">
17<h2>{% trans "Delete Agenda Item" %}</h2>
18
19{% if agenda_item_object.children.all %}
20<p>
21Deleting this Agenda Item will also delete the following Agenda Items:
22</p>
23{% recurse item.children.all with agenda_item_object.children.all as item %}
24 <ol class="agenda-list">
25 {% loop %}
26 <li class="agenda-item">
27 <a class="agenda-title" title="{% trans 'Update Agenda Item:' %} {{item.title}}" href="{% url agenda-item-update team_meeting_object.id item.id %}">{{ item.title }}</a>
28 - <a class="agenda-sig" target="launchpaduser" href="https://launchpad.net/~{{ item.owner.user.username}}">{{ item.owner.realname }}</a>
29 @ {{ item.created_date|date:"D, d N Y H:i T" }}
30 </li>
31 {% child %}
32 {% endloop %}
33 </ol>
34{% endrecurse %}
35{% endif %}
36
37<p>{% blocktrans with agenda_item_object.title as itemname %}Do you really want to delete the Agenda Item: {{itemname}}?{% endblocktrans %}</p>
38
39<form action="." method="post">
40 <p><input type="submit" value="Submit" /> <a href="{{team_meeting_object.get_absolute_url}}">{% trans "Cancel" %}</a></p>
41</form>
42</article>
43{% endblock %}
044
=== added file 'loco_directory/templates/meetings/agenda_item_new.html'
--- loco_directory/templates/meetings/agenda_item_new.html 1970-01-01 00:00:00 +0000
+++ loco_directory/templates/meetings/agenda_item_new.html 2011-01-24 02:52:15 +0000
@@ -0,0 +1,36 @@
1{% extends "base.html" %}
2{% load i18n %}
3
4{% block title %}{% trans "New Agenda Item" %} | {% trans "Ubuntu LoCo Team Directory" %} {% endblock %}
5
6{% block sub_nav_links %}
7<a class="sub-nav-item" href="{% url team-meeting-detail team_meeting_object.id %}">{% trans "Back to Meeting Details" %}</a>
8{% endblock %}
9
10{% block extrahead %}{{ block.super }}
11{{form.media}}
12{% endblock %}
13
14{% block extrafooter %}
15<script type="text/javascript"><!--
16$(document).ready(function(){
17 $('span[rel*=help]').colorTip({color:'orange'});
18});
19--></script>
20{% endblock %}
21
22{% block content %}
23<article class="main-content">
24<h2>{% trans "Add new Agenda Item for " %}{{ team_meeting_object.name}}</h2>
25<form action="." method="post">
26 <div class="form" style="width:auto;">
27 {{ form.as_template }}
28 <div>
29 {% if is_popup %}<input type="hidden" name="_popup" value="1">{% endif %}
30 <input type="submit" name="submit" value="{% trans "Submit" %}" class="submit-button" />
31 </div>
32 </div>
33</form>
34</article>
35
36{% endblock %}
037
=== added file 'loco_directory/templates/meetings/agenda_item_update.html'
--- loco_directory/templates/meetings/agenda_item_update.html 1970-01-01 00:00:00 +0000
+++ loco_directory/templates/meetings/agenda_item_update.html 2011-01-24 02:52:15 +0000
@@ -0,0 +1,37 @@
1{% extends "base.html" %}
2{% load i18n admin_modify adminmedia %}
3
4{% block title %}{% trans "Update Agenda Item" %} | {% trans "Ubuntu LoCo Team Directory" %} {% endblock %}
5
6{% block sub_nav_links %}
7<a class="sub-nav-item" href="{% url team-meeting-detail team_meeting_object.id %}">{% trans "Back to Meeting Details" %}</a>
8<a class="sub-nav-item" href="{% url agenda-item-delete team_meeting_object.id agenda_item_object.id %}">{% trans "Delete Agenda Item" %}</a>
9{% endblock %}
10
11{% block extrahead %}{{ block.super }}
12{{form.media}}
13{% endblock %}
14
15{% block extrafooter %}
16<script type="text/javascript"><!--
17$(document).ready(function(){
18 $('span[rel*=help]').colorTip({color:'orange'});
19});
20--></script>
21{% endblock %}
22
23{% block content %}
24<article class="main-content">
25<h2>{% trans "Update Agenda Item" %}</h2>
26<form action="." method="post">
27 <div class="form" style="width:auto;">
28 {{ form.as_template }}
29 <div>
30 {% if is_popup %}<input type="hidden" name="_popup" value="1">{% endif %}
31 <input type="submit" name="submit" value="{% trans "Submit" %}" class="submit-button" />
32 </div>
33 </div>
34</form>
35</article>
36
37{% endblock %}
038
=== modified file 'loco_directory/templates/meetings/team_meeting_detail_agenda.inc.html'
--- loco_directory/templates/meetings/team_meeting_detail_agenda.inc.html 2010-12-16 13:01:35 +0000
+++ loco_directory/templates/meetings/team_meeting_detail_agenda.inc.html 2011-01-24 02:52:15 +0000
@@ -1,10 +1,24 @@
1{% load i18n %}1{% load i18n %}
2{% load recurse %}
3 <p>
4 <a href="{% url agenda-item-new team_meeting_object.id %}">{% trans 'Add Agenda Item' %}</a>
5 </p>
2{% if team_meeting_object.agenda %}6{% if team_meeting_object.agenda %}
3<ol class="agenda-list">7 {% recurse item.children.all with team_meeting_object.agenda.top as item %}
4{% for item in team_meeting_object.agenda.as_tree %}8 <ol class="agenda-list">
5{{item.as_ol|safe}}9 {% loop %}
6{% endfor %}10 <li class="agenda-item">
7</ol>11 <a class="agenda-title" title="{% trans 'Update Agenda Item:' %} {{item.title}}" href="{% url agenda-item-update team_meeting_object.id item.id %}">{{ item.title }}</a>
12 - <a class="agenda-sig" target="launchpaduser" href="https://launchpad.net/~{{ item.owner.user.username}}">{{ item.owner.realname }}</a>
13 @ {{ item.created_date|date:"D, d N Y H:i T" }}
14 {% if item.description %}
15 <div class="agenda-description">{{ item.description|linebreaks }}</div>
16 {% endif %}
17 </li>
18 {% child %}
19 {% endloop %}
20 </ol>
21 {% endrecurse %}
8{% else %}22{% else %}
9<p>{% trans "There are currently no items on the agenda." %}</p>23<p>{% trans "There are currently no items on the agenda." %}</p>
10{% endif %}24{% endif %}
1125
=== modified file 'loco_directory/templates/site_search.html'
--- loco_directory/templates/site_search.html 2010-11-20 18:33:39 +0000
+++ loco_directory/templates/site_search.html 2011-01-24 02:52:15 +0000
@@ -57,6 +57,22 @@
57<hr class="divide" />57<hr class="divide" />
58{% endif %}58{% endif %}
5959
60{% if meetings %}
61<article class="main-content">
62 <h2>{% trans "Meetings" %}</h2>
63 {{colcycle.reset}}
64 <ul>
65 {% for meeting in meetings %}
66 <li class="{{colcycle.next}}"><a href="{{ meeting.get_absolute_url }}">{{ meeting.name }}</a>
67 {{ meeting.date_begin|date:"D, d N Y H:i T" }}
68 - {% for team in meeting.teams.all %}<a title="{% trans "more information about this team" %}" href="{{ team.get_absolute_url }}">{{ team.name }}</a>{% endfor %}
69 </li>
70 {% endfor %}
71 </ul>
72</article>
73<hr class="divide" />
74{% endif %}
75
60{% else %}76{% else %}
61<article class="main-content alone">77<article class="main-content alone">
62 <center>78 <center>

Subscribers

People subscribed via source and target branches