Add group_detail members table pagination
authorSofia Papagiannaki <papagian@gmail.com>
Thu, 27 Sep 2012 17:00:06 +0000 (20:00 +0300)
committerSofia Papagiannaki <papagian@gmail.com>
Thu, 27 Sep 2012 17:00:06 +0000 (20:00 +0300)
snf-astakos-app/astakos/im/models.py
snf-astakos-app/astakos/im/templates/im/astakosgroup_detail.html
snf-astakos-app/astakos/im/templatetags/filters.py
snf-astakos-app/astakos/im/urls.py
snf-astakos-app/astakos/im/views.py

index 3c82b6d..6b62bed 100644 (file)
@@ -120,22 +120,17 @@ class AstakosGroup(Group):
         'Homepage Url', max_length=255, null=True, blank=True)
     desc = models.TextField('Description', null=True)
     policy = models.ManyToManyField(Resource, null=True, blank=True,
-                                    through='AstakosGroupQuota'
-                                    )
+                                    through='AstakosGroupQuota')
     creation_date = models.DateTimeField('Creation date',
-                                         default=datetime.now()
-                                         )
+                                         default=datetime.now())
     issue_date = models.DateTimeField('Issue date', null=True)
     expiration_date = models.DateTimeField('Expiration date', null=True)
     moderation_enabled = models.BooleanField('Moderated membership?',
-                                             default=True
-                                             )
+                                             default=True)
     approval_date = models.DateTimeField('Activation date', null=True,
-                                         blank=True
-                                         )
+                                         blank=True)
     estimated_participants = models.PositiveIntegerField('Estimated #members',
-                                                         null=True
-                                                         )
+                                                         null=True)
 
     @property
     def is_disabled(self):
index 1bc1974..ec62573 100644 (file)
@@ -6,20 +6,20 @@
 <div class="projects">
        
        <h2>
-               {% if request.user in object.members %}
+               {% if object.is_member %}
                        <em>
-                               {% if request.user in object.owner.all %}
+                               {% if object.is_owner %}
                                        [ADMINISTRATOR]
                                {%  else %}
                                        [ ENROLLED ]
                                {% endif %}
                        </em>           
                {% endif %}
-               <span>[ {{object.kind|upper}} ]</span>  
+               <span>[ {{object.kindname|upper}} ]</span>
         </h2>
         
         <div class="details">
-               {% if request.user in object.owner.all %}
+               {% if object.is_owner %}
                        <a href="#" class="edit">[ EDIT GROUP INFO ]</a>
                {% endif %}
                <div class="data">
                         </dl>
                </div>
                <div class="editable" style="display:none;">
-               <form action="{% url astakos.im.views.group_update object.id %}" method="post"
+               <form action="" method="post"
                    class="withlabels">{% csrf_token %}
-                   {% include "im/form_render.html" %}
-                   <div class="form-row submit">
-                       <input type="submit" class="submit altcol" value="FINISHED EDITING" />
-                   </div>
+                   {% with update_form as form %}
+                    {% include "im/form_render.html" %}
+                    <div class="form-row submit">
+                        <input type="submit" class="submit altcol" value="FINISHED EDITING" />
+                    </div>
+                   {% endwith %}
            </form>
                </div>
         </div>
@@ -51,7 +53,7 @@
                        <dt>Name</dt>
                        <dd>{{object.name}}&nbsp;</dd>
                        <dt>Type</dt>
-                       <dd>{{object.kind|capfirst}}&nbsp;</dd>
+                       <dd>{{object.kindname|capfirst}}&nbsp;</dd>
                        <dt>Issue date:</dt>
                        <dd>{{object.issue_date|date:"d/m/Y"}}&nbsp;</dd>
                        <dt>Expiration Date</dt>
         
      <div class="full-dotted">
                 <h3>RESOURCES:</h3>
-                {% if quota %}
+                {% if object.quota %}
                 <dl class="alt-style">
                         
-                       {% for k in quota|dkeys %}
+                       {% for k in object.quota|dkeys %}
                 
                 <dt>{{ k }}</dt>
-                <dd>{{ quota|lookup:k }}&nbsp;</dd>
+                <dd>{{ object.quota|lookup:k }}&nbsp;</dd>
                   
             {% endfor %}
                </dl>
         {% endif %} 
         </div>
         <div class="full-dotted">
-               {% if object.members %}
-               <form method="GET" class="minimal" action=""> 
-                       <div class="form-row">
-                               <select name="sorting" onchange="this.form.submit();">
-                                   <option value="">Sort by</option>
-                                   <option value="email" {% if sorting == 'email' %}selected{% endif %}>User Id</option>
-                           <option value="realname" {% if sorting == 'realname' %}selected{% endif %}>Name</option>                    
-                           <option value="is_approved" {% if sorting == 'is_approved' %}selected{% endif %}>Status</option>                    
-                               </select>
-                               <input type="hidden" name="q" value="{{q}}"/>
-                       </div>
-               </form>
-                <table class="alt-style">
-                       <caption>MEMBERS:</caption>
-                       <thead>
-                               <tr>
-                                       <th>User Id</th>
-                                       <th>Name</th>
-                                       <th>Status</th>
-                               </tr>
-                       </thead>
-                       <tbody>
-                       {% for p in members.object_list %}
-              <tr>
-                <td>{{p.email}}</td>
-                <td>{{p.realname}}</td>
-                {% if p in object.owner.all %}
-                <td>Owner</td>
-                {% else %}
-                    {% if p.is_approved %}
-                    <td>Approved</td>
+           {% with page|concat:sorting as args %}
+           {% with object.members|paginate:args as members%}
+            {% if members %}
+            <form method="GET" class="minimal" action="">
+                <div class="form-row">
+                    <select name="sorting" onchange="this.form.submit();">
+                        <option value="">Sort by</option>
+                        <option value="email" {% if sorting == 'email' %}selected{% endif %}>User Id</option>
+                        <option value="realname" {% if sorting == 'realname' %}selected{% endif %}>Name</option>
+                        <option value="is_approved" {% if sorting == 'is_approved' %}selected{% endif %}>Status</option>
+                    </select>
+                </div>
+            </form>
+             <table class="alt-style">
+                <caption>MEMBERS:</caption>
+                <thead>
+                    <tr>
+                        <th>User Id</th>
+                        <th>Name</th>
+                        <th>Status</th>
+                    </tr>
+                </thead>
+                <tbody>
+                {% for p in members.object_list %}
+                  <tr>
+                    <td>{{p.email}}</td>
+                    <td>{{p.realname}}</td>
+                    {% if p in object.owner.all %}
+                    <td>Owner</td>
                     {% else %}
-                    <td>Pending 
-                        {% if user in object.owner.all %}
-                            <a href="{% url approve_member m.group.id m.person.id %}">Accept</a>
-                            <a href="{% url disapprove_member m.group.id m.person.id  %}">Reject</a>
+                        {% if p.is_approved %}
+                        <td>Approved</td>
+                        {% else %}
+                        <td>Pending 
+                            {% if user in object.owner.all %}
+                                <a href="{% url approve_member m.group.id m.person.id %}">Accept</a>
+                                <a href="{% url disapprove_member m.group.id m.person.id  %}">Reject</a>
+                            {% endif %}
+                        </td>    
                         {% endif %}
-                    </td>    
                     {% endif %}
-                {% endif %}
-              </tr>
-            {% endfor %}
-            </tbody>
-                </table>
-                <div class="pagination">
-                       <p class="next-prev">
-                       {% if members.has_previous %}
-                       <a href="?page={{ members.previous_page_number }}{% if sorting %}&sorting={{sorting}}{% endif %}">previous</a>
-                   {% endif %}
-                   {% if members.has_next %}
-                       <a href="?page={{ members.next_page_number }}{% if sorting %}&sorting={{sorting}}{% endif %}">next</a>
-                   {% endif %}
-               </p>
-                       <p class="nums">
-                               <span class="current">
-                       Page {{ members.number }} of {{ members.paginator.num_pages }}
-                   </span>
-                       </p>
-           </div>
-                {% else %}
-            <p>No members yet!</p>
-        {% endif %}
+                  </tr>
+                {% endfor %}
+                </tbody>
+             </table>
+             <div class="pagination">
+                <p class="next-prev">
+                    {% if members.has_previous %}
+                        <a href="?page={{ members.previous_page_number }}{% if sorting %}&sorting={{sorting}}{% endif %}">previous</a>
+                    {% endif %}
+                    {% if members.has_next %}
+                        <a href="?page={{ members.next_page_number }}{% if sorting %}&sorting={{sorting}}{% endif %}">next</a>
+                    {% endif %}
+                </p>
+                <p class="nums">
+                    <span class="current">
+                        Page {{ members.number }} of {{ members.paginator.num_pages }}
+                    </span>
+                </p>
+            </div>
+             {% else %}
+                <p>No members yet!</p>
+            {% endif %}
+        {% endwith %}
+        {% endwith %}
         </div>
      
      
-    {% if user in object.owner.all %}
+    {% if object.is_owner %}
     <div class="full-dotted">
-        <form action="{% url add_members object.id %}" method="post" class="withlabels">{% csrf_token %}
+        <form action="" method="post" class="withlabels">{% csrf_token %}
             <h2>Enroll more members</h2>
-                {% with search_form as form %}
+                {% with addmembers_form as form %}
                     {% include "im/form_render.html" %}
                 {% endwith %}
                 <div class="form-row submit">
index c0c9edb..2657d2f 100644 (file)
@@ -35,11 +35,14 @@ import calendar
 import datetime
 
 from django import template
+from django.core.paginator import Paginator, InvalidPage
 
 from astakos.im.settings import PAGINATE_BY
 
 register = template.Library()
 
+DELIM = ','
+
 @register.filter
 def monthssince(joined_date):
     now = datetime.datetime.now()
@@ -88,4 +91,33 @@ def todate(value, arg = ''):
 
 @register.filter
 def rcut(value, chars = '/'):
-    return value.rstrip(chars)
\ No newline at end of file
+    return value.rstrip(chars)
+
+@register.filter
+def paginate(l, args):
+    page, delim, sorting = args.partition(DELIM)
+    if sorting:
+        l.sort(key=lambda i: getattr(i, sorting))
+    paginator = Paginator(l, PAGINATE_BY)
+    
+    try:
+        page_number = int(page)
+    except ValueError:
+        if page == 'last':
+            page_number = paginator.num_pages
+        else:
+            page_number = 1
+    page = globals()['page'] = paginator.page(page_number)
+    return page
+
+@register.filter
+def concat(str1, str2):
+    if not str2:
+        return str(str1)
+    return '%s%s%s' % (str1, DELIM, str2)
+
+@register.filter
+def concat(str1, str2):
+    if not str2:
+        return str(str1)
+    return '%s%s%s' % (str1, DELIM, str2)
\ No newline at end of file
index 86ba91f..3759b78 100644 (file)
@@ -66,8 +66,6 @@ urlpatterns = patterns('astakos.im.views',
                            'group_list', {}, name='group_list'),
                        url(r'^group/(?P<group_id>\d+)/?$', 'group_detail',
                            {}, name='group_detail'),
-                       url(r'^group/update/(?P<group_id>\d+)/?$',
-                           'group_update', {}, name='group_update'),
                        url(r'^group/search/?$',
                            'group_search', {}, name='group_search'),
                        url(r'^group/all/?$',
@@ -80,8 +78,6 @@ urlpatterns = patterns('astakos.im.views',
                            'approve_member', {}, name='approve_member'),
                        url(r'^group/(?P<group_id>\d+)/(?P<user_id>\d+)/disapprove/?$',
                            'disapprove_member', {}, name='disapprove_member'),
-                       url(r'^group/(?P<group_id>\d+)/add/?$',
-                           'add_members', {}, name='add_members'),
                        url(r'^group/create/?$', 'group_create_list', {},
                            name='group_create_list'),
                        )
index 5c2405c..feb91b7 100644 (file)
@@ -51,7 +51,7 @@ from django.db.models.fields import DateTimeField
 from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, \
     HttpResponseRedirect, HttpResponseBadRequest, Http404
 from django.shortcuts import redirect
-from django.template import RequestContext, loader
+from django.template import RequestContext, loader as template_loader
 from django.utils.http import urlencode
 from django.utils.translation import ugettext as _
 from django.views.generic.create_update import (create_object, delete_object,
@@ -59,6 +59,7 @@ from django.views.generic.create_update import (create_object, delete_object,
 from django.views.generic.list_detail import object_list, object_detail
 from django.http import HttpResponseBadRequest
 from django.core.paginator import Paginator, InvalidPage
+from django.core.xheaders import populate_xheaders
 
 from astakos.im.models import (
     AstakosUser, ApprovalTerms, AstakosGroup, Resource,
@@ -98,7 +99,7 @@ def render_response(template, tab=None, status=200, reset_cookie=False,
     if tab is None:
         tab = template.partition('_')[0].partition('.html')[0]
     kwargs.setdefault('tab', tab)
-    html = loader.render_to_string(
+    html = template_loader.render_to_string(
         template, kwargs, context_instance=context_instance)
     response = HttpResponse(html, status=status)
     if reset_cookie:
@@ -791,62 +792,67 @@ def group_list(request):
 @signed_terms_required
 @login_required
 def group_detail(request, group_id):
+    q = AstakosGroup.objects.filter(pk=group_id)
+    q = q.extra(select={
+        'is_member': """SELECT CASE WHEN EXISTS(
+                            SELECT id FROM im_membership
+                            WHERE group_id = im_astakosgroup.group_ptr_id
+                            AND person_id = %s)
+                        THEN 1 ELSE 0 END""" % request.user.id,
+        'is_owner': """SELECT CASE WHEN EXISTS(
+                            SELECT id FROM im_astakosuser_owner
+                            WHERE astakosgroup_id = im_astakosgroup.group_ptr_id
+                            AND astakosuser_id = %s)
+                        THEN 1 ELSE 0 END""" % request.user.id,
+        'kindname': """SELECT name FROM im_groupkind
+                       WHERE id = im_astakosgroup.kind_id"""})
+    
+    model = q.model
+    context_processors = None
+    mimetype = None
     try:
-        group = AstakosGroup.objects.select_related().get(id=group_id)
-    except AstakosGroup.DoesNotExist:
-        return HttpResponseBadRequest(_('Invalid group.'))
-    form = AstakosGroupUpdateForm(instance=group)
-    add_members_form = AddGroupMembersForm()
+        obj = q.get()
+    except ObjectDoesNotExist:
+        raise Http404("No %s found matching the query" % (model._meta.verbose_name))
     
-    # build members
-    page = request.GET.get('page', 1)
-    sorting = request.GET.get('sorting')
-    if sorting:
-        group.members.sort(key=lambda i: getattr(i, sorting))
-    paginator = Paginator(group.members, PAGINATE_BY)
+    update_form = AstakosGroupUpdateForm(instance=obj)
+    addmembers_form = AddGroupMembersForm()
+    if request.method == 'POST':
+        update_data = {}
+        addmembers_data = {}
+        for k,v in request.POST.iteritems():
+            if k in update_form.fields:
+                update_data[k] = v
+            if k in addmembers_form.fields:
+                addmembers_data[k] = v
+        update_data = update_data or None
+        addmembers_data = addmembers_data or None
+        update_form = AstakosGroupUpdateForm(update_data, instance=obj)
+        addmembers_form = AddGroupMembersForm(addmembers_data)
+        if update_form.is_valid():
+            update_form.save()
+        if addmembers_form.is_valid():
+            map(obj.approve_member, addmembers_form.valid_users)
+            addmembers_form = AddGroupMembersForm()
     
-    try:
-        page_number = int(page)
-    except ValueError:
-        if page == 'last':
-            page_number = paginator.num_pages
+    template_name = "%s/%s_detail.html" % (model._meta.app_label, model._meta.object_name.lower())
+    t = template_loader.get_template(template_name)
+    c = RequestContext(request, {
+        'object': obj,
+    }, context_processors)
+    extra_context = {'update_form': update_form,
+                     'addmembers_form': addmembers_form,
+                     'page': request.GET.get('page', 1),
+                     'sorting': request.GET.get('sorting')}
+    for key, value in extra_context.items():
+        if callable(value):
+            c[key] = value()
         else:
-            # Page is not 'last', nor can it be converted to an int.
-            raise Http404
-    try:
-        members_page = globals()['page'] = paginator.page(page_number)
-    except InvalidPage:
-        raise Http404
-    return object_detail(request,
-                         AstakosGroup.objects.all(),
-                         object_id=group_id,
-                         extra_context={'quota': group.quota,
-                                        'form': form,
-                                        'search_form': add_members_form,
-                                        'members': members_page,
-                                        'sorting': sorting}
-                         )
-
+            c[key] = value
+    response = HttpResponse(t.render(c), mimetype=mimetype)
+    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
+    return response
 
-@signed_terms_required
-@login_required
-def group_update(request, group_id):
-    if request.method != 'POST':
-        return HttpResponseBadRequest('Method not allowed.')
-    try:
-        group = AstakosGroup.objects.select_related().get(id=group_id)
-    except AstakosGroup.DoesNotExist:
-        return HttpResponseBadRequest(_('Invalid group.'))
-    form = AstakosGroupUpdateForm(request.POST, instance=group)
-    if form.is_valid():
-        form.save()
-    search_form = AddGroupMembersForm()
-    return object_detail(request,
-                         AstakosGroup.objects.all(),
-                         object_id=group_id,
-                         extra_context={'quota': group.quota,
-                                        'form': form,
-                                        'search_form': search_form})
 
 @signed_terms_required
 @login_required
@@ -1029,31 +1035,6 @@ def disapprove_member(request, membership):
         messages.error(request, msg)
 
 
-
-
-@signed_terms_required
-@login_required
-def add_members(request, group_id):
-    if request.method != 'POST':
-        return HttpResponseBadRequest(_('Bad method'))
-    try:
-        group = AstakosGroup.objects.select_related().get(id=group_id)
-    except AstakosGroup.DoesNotExist:
-        return HttpResponseBadRequest(_('Invalid group.'))
-    search_form = AddGroupMembersForm(request.POST)
-    if search_form.is_valid():
-        users = search_form.get_valid_users()
-        map(group.approve_member, users)
-        search_form = AddGroupMembersForm()
-    form = AstakosGroupUpdateForm(instance=group)
-    return object_detail(request,
-                         AstakosGroup.objects.all(),
-                         object_id=group_id,
-                         extra_context={'quota': group.quota,
-                                        'form': form,
-                                        'search_form' : search_form})
-
-
 @signed_terms_required
 @login_required
 def resource_list(request):