Merge branch 'dev' of https://code.grnet.gr/git/astakos into dev
authorroot <root@dev84.dev.grnet.gr>
Tue, 25 Sep 2012 13:15:37 +0000 (16:15 +0300)
committerroot <root@dev84.dev.grnet.gr>
Tue, 25 Sep 2012 13:15:37 +0000 (16:15 +0300)
Conflicts:
snf-astakos-app/astakos/im/forms.py
snf-astakos-app/astakos/im/views.py

snf-astakos-app/astakos/im/forms.py
snf-astakos-app/astakos/im/functions.py
snf-astakos-app/astakos/im/migrations/0023_populate_resource_data.py
snf-astakos-app/astakos/im/static/im/css/forms.css
snf-astakos-app/astakos/im/templates/im/astakosgroup_list.html
snf-astakos-app/astakos/im/templatetags/filters.py
snf-astakos-app/astakos/im/views.py

index ce9eb0b..341a356 100644 (file)
@@ -621,3 +621,7 @@ class TimelineForm(forms.Form):
             d['end_date'] = d['end_date'].strftime("%Y-%m-%dT%H:%M:%S.%f")[:24]
         return d
 
+class AstakosGroupSortForm(forms.Form):
+    sort_by = forms.ChoiceField(label='Sort by',
+                                choices=(('groupname', 'Name'), ('kindname', 'Type')),
+                                required=False)
index 1d13659..d28c57e 100644 (file)
@@ -51,8 +51,7 @@ from datetime import datetime
 from functools import wraps
 
 from astakos.im.settings import (DEFAULT_CONTACT_EMAIL, SITENAME, BASEURL,
-                                 LOGGING_LEVEL
-                                 )
+                                 LOGGING_LEVEL)
 from astakos.im.models import AstakosUser
 
 logger = logging.getLogger(__name__)
index cd60d9b..0f1d1ad 100644 (file)
@@ -19,7 +19,8 @@ class Migration(DataMigration):
             sn, dict = args
             url = dict.get('url') 
             policy = dict.get('quota') or ()
-            s, created = orm.Service.objects.get_or_create(name=sn, url=url)
+            s, created = orm.Service.objects.get_or_create(name=sn,
+                                                           defaults={'url': url})
             if not created and not s.url:
                 s.url = url
                 s.save()
index f03121a..f016797 100644 (file)
@@ -156,7 +156,9 @@ form.link-like input[type="submit"]:hover           { text-decoration:underline;  }
 .projects form .with-checkbox                                  { margin:20px 0; }\r
 .projects form .with-checkbox label                            { padding-top:7px; }\r
 .projects form .with-checkbox span.info                        { bottom:24px; }\r
-\r
+.projects .minimal                                                             { float:right; position:relative; margin-bottom:-20px;}\r
+.projects .minimal select                                              { padding:3px; width:250px; }\r
+.projects .minimal label                                               { position:absolute; right:290px; top:5px; white-space:nowrap}\r
 \r
 @media screen and (max-width : 630px)          { \r
        form.withlabels .extra-img                                      { left:260px; }\r
index f870c06..180e5c1 100644 (file)
@@ -21,7 +21,7 @@
     </form>
     {% else %}
     <div class="projects">
-               <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br />You can <a href="{% url group_create_list %}">create a new group</a> or <a href="{% url group_search %}">join</a> to an existing one.</p>
+               <!--<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br />You can <a href="{% url group_create_list %}">create a new group</a> or <a href="{% url group_search %}">join</a> to an existing one.</p>
                 
                <ul class="widjets clearfix">   
                        <li>
                                        <p class="btn"><a href="{% url group_search %}" class="submit">JOIN</a></p>
                                </div>
                        </li>
-               </ul>
+               </ul>-->
         
     {% endif %}
-    {% with page_obj.object_list|enabled:is_search as object_list %}
+    {% with page_obj.object_list as object_list %}
     {% if object_list %}
         <div class="full-dotted">
             <table class="alt-style complex">
                 <caption>
-                    {% if is_search %}
-                        SEARCH RESULTS
-                    {% else %}
-                        I PARTICIPATE IN
-                    {% endif %}
+                    SEARCH RESULTS
                 </caption>
                 <thead>
                   <tr>
                 </thead>
                 <tbody>
                   {% for o in object_list %}
-                  <tr class="{% cycle 'tr1' 'tr2' %}">
-                    <td><a href="{% url group_detail o.id %}" title="visit group page">{{o.name|cut:"http://"|cut:"/" }}</a></td>
-                    <td>{{o.kind|capfirst}}</td>
+                    <tr class="{% cycle 'tr1' 'tr2' %}">
+                    <td><a href="{% url group_detail o.id %}" title="visit group page">{{o.groupname|rcut:"/"}}</a></td>
+                    <td>{{o.kindname|capfirst}}</td>
                     <td>{{o.issue_date|date:"d/m/Y"}}</td>
                     <td>{{o.expiration_date|date:"d/m/Y"}}</td>
-                    
-                    <td>{{ o.approved_members|length }}</td>
+                    <td>{{o.approved_members_num}}</td>
                     
                     <td>
-                    {% if user in o.approved_members %}
+                    {% if o.is_member %}
+                        {% if o.membership_approval_date %}
     
                         Registered
                         <form action="{% url group_leave o.id %}" method="post" class="link-like">{% csrf_token %}
                         </form>        
                         
                             
-                    {% else %}
-                        {% if user in o.members %}
-                            Pending
+
                         {% else %}
+                            Pending
+                        {% endif %}
+                    {% else %}
                             Not member 
                                 <form action="{% url group_join o.id %}" method="post" class="link-like">{% csrf_token %}
                                     <input type="submit"   value="JOIN GROUP" />
                                 </form>
                             
-                        {% endif %}
                     {% endif %}
                     </td>
                     <td><a href="#" class="more-info" title="more info">&nbsp;</a></td>
                         <div>
                             <p>{{o.desc}}</p>
                             <p>{% if o.homepage%}
-                                Visit it group's home page: <a href="{{ o.homepage }}">{{ o.homepage }}</a>
+                                Visit it group's home page: <a target="_blank" href="{{ o.homepage }}">{{ o.homepage }}</a>
                             {% else %}
                                 There is no homepage for this group yet.
                             {% endif %}
             </table>
            
         </div>
+        
+     
     <div class="pagination">
-        <span class="step-links">
-            {% if page_obj.has_previous %}
+               <p class="next-prev">
+               {% if page_obj.has_previous %}
                 <a href="?page={{ page_obj.previous_page_number }}{% if q %}&q={{q}}{% endif %}">previous</a>
             {% endif %}
-    
-            <span class="current">
-                Page {{ page_obj.number }} of {{ paginator.num_pages }}.
-            </span>
-    
             {% if page_obj.has_next %}
                 <a href="?page={{ page_obj.next_page_number }}{% if q %}&q={{q}}{% endif %}">next</a>
             {% endif %}
-        </span>
-    </div>
+       </p>
+               <p class="nums">
+                       <span class="current">
+                Page {{ page_obj.number }} of {{ paginator.num_pages }}
+            </span>
+               </p>
+   </div>
       {% else %}
                {% if mine %}
                    <div class="full-dotted">
+                                       <form method="GET" class="minimal" action="">
+                                               <div class="form-row">
+                                                   <select name="own_sorting" onchange="this.form.submit();">
+                                                           <option value="">Sort by</option>
+                                                           <option value="groupname" {% if own_sorting == 'groupname' %}selected{% endif %}>Name</option>
+                                                   <option value="kindname" {% if own_sorting == 'kindname' %}selected{% endif %}>Type</option>                                
+                                                       </select>
+                                               </div>
+                                       </form>
                                        <table class="alt-style complex" id="">
                                    <caption>MY GROUPS</caption>
                                    <thead>
                                    <tbody>
                                      {% for o in mine.object_list %}
                                      <tr class="{% cycle 'tr1' 'tr2' %}">
-                                       <td><a  href="{% url group_detail o.id %}" title="visit group page">{{o.name|cut:"http://"|cut:"/" }}</a></td>
-                                       <td>{{o.kind|capfirst}}</td>
+                                       <td><a  href="{% url group_detail o.id %}" title="visit group page">{{o.groupname|rcut:"/" }}</a></td>
+                                       <td>{{o.kindname|capfirst}}</td>
                                        <td>{{o.issue_date|date:"d/m/Y"}}</td>
                                        <td>{{o.expiration_date|date:"d/m/Y"}}</td>
-                                       <td>{{ o.approved_members|length }}</td>
+                                       <td>{{ o.approved_members_num }}</td>
                                        <td>{% if o.is_enabled %}Active{% else %}Pending{% endif %}</td>
                                        <td>{% if o.moderation_enabled%}Yes{% else %}No{% endif %}</td>
                                        <td><a href="#" class="more-info" title="more info">&nbsp;</a></td>
                                </table>
                                </div>
                                <div class="pagination">
-                    <span class="step-links">
-                        {% if mine.has_previous %}
-                            <a href="?own_page={{ mine.previous_page_number }}">previous</a>
+                                       <p class="next-prev">
+                                       {% if mine.has_previous %}
+                            <a href="?own_page={{ mine.previous_page_number }}{% if own_sorting %}&own_sorting={{ own_sorting }}{% endif%}{% if other_sorting %}&other_sorting={{ other_sorting }}{% endif%}">previous</a>
                         {% endif %}
-                
-                        <span class="current">
-                            Page {{ mine.number }} of {{ mine.paginator.num_pages }}.
-                        </span>
-                
-                        {% if mine.has_next %}
-                            <a href="?own_page={{ mine.next_page_number }}">next</a>
+                                   {% if mine.has_next %}
+                            <a href="?own_page={{ mine.next_page_number }}{% if own_sorting %}&own_sorting={{ own_sorting }}{% endif%}{% if other_sorting %}&other_sorting={{ other_sorting }}{% endif%}">next</a>
                         {% endif %}
-                    </span>
-                </div>
+                               </p>
+                                       <p class="nums">
+                                               <span class="current">
+                            Page {{ mine.number }} of {{ mine.paginator.num_pages }}
+                        </span>
+                                       </p>
+                          </div>
+                                
                {% endif %}
                {% if other %}  
                        <div class="full-dotted">
+                               <form method="GET" class="minimal" action="">
+                                               <div class="form-row">
+                                                       <select name="other_sorting" onchange="this.form.submit();">
+                                                           <option value="">Sort by</option>
+                                                           <option value="groupname" {% if other_sorting == 'groupname' %}selected{% endif %}>Name</option>
+                                                   <option value="kindname" {% if other_sorting == 'kindname' %}selected{% endif %}>Type</option>                      
+                                                       </select>
+                                               </div>
+                                       </form>
                                        <table class="alt-style complex">
                                    <caption>
-                                       {% if is_search %}
-                                               SEARCH RESULTS
-                                           {% else %}
-                                               I PARTICIPATE IN
-                                       {% endif %}
+                                       I PARTICIPATE IN
                                    </caption>
                                    <thead>
                                      <tr>
                                    <tbody>
                                      {% for o in other.object_list %}
                                      <tr class="{% cycle 'tr1' 'tr2' %}">
-                                       <td><a href="{% url group_detail o.id %}" title="visit group page">{{o.name|cut:"http://"|cut:"/" }}</a></td>
-                                       <td>{{o.kind|capfirst}}</td>
+                                       <td><a href="{% url group_detail o.id %}" title="visit group page">{{o.groupname|rcut:"/"}}</a></td>
+                                       <td>{{o.kindname|capfirst}}</td>
                                        <td>{{o.issue_date|date:"d/m/Y"}}</td>
                                        <td>{{o.expiration_date|date:"d/m/Y"}}</td>
                                        
-                                       <td>{{ o.approved_members|length }}</td>
+                                       <td>{{ o.approved_members_num }}</td>
                                        
                                        <td>
-                                       {% if user in o.approved_members %}
+                                       {% if o.membership_approval_date %}
                        
                                        Registered
                                        <form action="{% url group_leave o.id %}" method="post" class="link-like">{% csrf_token %}
                                            
                                                
                                        {% else %}
-                                           {% if user in o.members %}
-                                               Pending
-                                           {% else %}
-                                               Not member 
-                                                   <form action="{% url group_join o.id %}" method="post" class="link-like">{% csrf_token %}
-                                                       <input type="submit"   value="JOIN GROUP" />
-                                                   </form>
-                                               
-                                           {% endif %}
+                                           Pending
                                        {% endif %}
                                        </td>
                                        <td><a href="#" class="more-info" title="more info">&nbsp;</a></td>
                               
                                </div>
                                <div class="pagination">
-                    <span class="step-links">
-                        {% if other.has_previous %}
-                            <a href="?other_page={{ other.previous_page_number }}">previous</a>
+                                       <p class="next-prev">
+                                       {% if other.has_previous %}
+                            <a href="?other_page={{ other.previous_page_number }}{% if own_sorting %}&own_sorting={{ own_sorting }}{% endif%}{% if other_sorting %}&other_sorting={{ other_sorting }}{% endif%}">previous</a>
                         {% endif %}
-                
-                        <span class="current">
-                            Page {{ other.number }} of {{ other.paginator.num_pages }}.
-                        </span>
-                
-                        {% if other.has_next %}
-                            <a href="?other_page={{ other.next_page_number }}">next</a>
+                                   {% if other.has_next %}
+                            <a href="?other_page={{ other.next_page_number }}{% if own_sorting %}&own_sorting={{ own_sorting }}{% endif%}{% if other_sorting %}&other_sorting={{ other_sorting }}{% endif%}">next</a>
                         {% endif %}
-                    </span>
-                </div>
+                               </p>
+                                       <p class="nums">
+                                               <span class="current">
+                            Page {{ other.number }} of {{ other.paginator.num_pages }}
+                        </span>
+                                       </p>
+                          </div>
+                                
                        {% endif %}
             {% if q %}
                 <h2>No groups found!</h2>
index 946e9f0..c0c9edb 100644 (file)
@@ -76,13 +76,6 @@ def dkeys(d):
 
 
 @register.filter
-def enabled(object_list, is_search):
-    if not is_search:
-        return object_list
-    return [g for g in object_list if g.is_enabled]
-
-
-@register.filter
 def month_name(month_number):
     return calendar.month_name[month_number]
     
@@ -90,4 +83,9 @@ def month_name(month_number):
 @register.filter
 def todate(value, arg = ''):
     secs = int(value) / 1000
-    return datetime.datetime.fromtimestamp(secs)
\ No newline at end of file
+    return datetime.datetime.fromtimestamp(secs)
+
+
+@register.filter
+def rcut(value, chars = '/'):
+    return value.rstrip(chars)
\ No newline at end of file
index 65a10b4..594a2d0 100644 (file)
@@ -37,6 +37,7 @@ import calendar
 from urllib import quote
 from functools import wraps
 from datetime import datetime, timedelta
+from collections import defaultdict
 
 from django.contrib import messages
 from django.contrib.auth.decorators import login_required
@@ -47,7 +48,7 @@ from django.db.models import Q
 from django.db.utils import IntegrityError
 from django.forms.fields import URLField
 from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, \
-    HttpResponseRedirect, HttpResponseBadRequest
+    HttpResponseRedirect, HttpResponseBadRequest, Http404
 from django.shortcuts import redirect
 from django.template import RequestContext, loader
 from django.utils.http import urlencode
@@ -68,7 +69,7 @@ from astakos.im.forms import (LoginForm, InvitationForm, ProfileForm,
                               ExtendedPasswordChangeForm, EmailChangeForm,
                               AstakosGroupCreationForm, AstakosGroupSearchForm,
                               AstakosGroupUpdateForm, AddGroupMembersForm,
-                              TimelineForm)
+                              AstakosGroupSortForm, TimelineForm)
 from astakos.im.functions import (send_feedback, SendMailError,
                                   invite as invite_func, logout as auth_logout,
                                   activate as activate_func,
@@ -84,6 +85,9 @@ from astakos.im.tasks import request_billing
 logger = logging.getLogger(__name__)
 
 
+DB_REPLACE_GROUP_SCHEME = """REPLACE(REPLACE("auth_group".name, 'http://', ''),
+                                     'https://', '')"""
+
 def render_response(template, tab=None, status=200, reset_cookie=False,
                     context_instance=None, **kwargs):
     """
@@ -718,14 +722,47 @@ def group_add(request, kind_name='default'):
 @signed_terms_required
 @login_required
 def group_list(request):
-    q = request.user.astakos_groups.none()
-    list = request.user.astakos_groups.select_related().all()
-    d = {}
-    d['own'] = [g for g in list if request.user in g.owner.all()]
-    d['other'] = list.exclude(id__in=(g.id for g in d['own']))
-    for k, queryset in d.iteritems():
-        paginator = Paginator(queryset, PAGINATE_BY)
+    none = request.user.astakos_groups.none()
+    q = AstakosGroup.objects.raw("""
+        SELECT auth_group.id,
+        %s AS groupname,
+        im_groupkind.name AS kindname,
+        im_astakosgroup.*,
+        owner.email AS groupowner,
+        (SELECT COUNT(*) FROM im_membership
+            WHERE group_id = im_astakosgroup.group_ptr_id
+            AND date_joined IS NOT NULL) AS approved_members_num,
+        (SELECT date_joined FROM im_membership
+            WHERE group_id = im_astakosgroup.group_ptr_id
+            AND person_id = %s) AS membership_approval_date
+        FROM im_astakosgroup
+        INNER JOIN im_membership ON (
+            im_astakosgroup.group_ptr_id = im_membership.group_id)
+        INNER JOIN auth_group ON(im_astakosgroup.group_ptr_id = auth_group.id)
+        INNER JOIN im_groupkind ON (im_astakosgroup.kind_id = im_groupkind.id)
+        LEFT JOIN im_astakosuser_owner ON (
+            im_astakosuser_owner.astakosgroup_id = im_astakosgroup.group_ptr_id)
+        LEFT JOIN auth_user as owner ON (
+            im_astakosuser_owner.astakosuser_id = owner.id)
+        WHERE im_membership.person_id = %s
+        """ % (DB_REPLACE_GROUP_SCHEME, request.user.id, request.user.id))
+    d = defaultdict(list)
+    for g in q:
+        if request.user.email == g.groupowner:
+            d['own'].append(g)
+        else:
+            d['other'].append(g)
+    
+    for k, l in d.iteritems():
         page = request.GET.get('%s_page' % k, 1)
+        sorting = globals()['%s_sorting' % k] = request.GET.get('%s_sorting' % k)
+        if sorting:
+            sort_form = AstakosGroupSortForm({'sort_by': sorting})
+            if sort_form.is_valid():
+                l.sort(key=lambda i: getattr(i, sorting))
+                globals()['%s_sorting' % k] = sorting
+        paginator = Paginator(l, PAGINATE_BY)
+        
         try:
             page_number = int(page)
         except ValueError:
@@ -735,13 +772,16 @@ def group_list(request):
                 # Page is not 'last', nor can it be converted to an int.
                 raise Http404
         try:
-            page_obj = locals()['%s_page_obj' % k] = paginator.page(page_number)
+            page_obj = globals()['%s_page_obj' % k] = paginator.page(page_number)
         except InvalidPage:
             raise Http404
-    return object_list(request, queryset=q,
+    return object_list(request, queryset=none,
                        extra_context={'is_search':False,
-                                      'mine': locals()['own_page_obj'],
-                                      'other': locals()['other_page_obj']})
+                                      'mine': own_page_obj,
+                                      'other': other_page_obj,
+                                      'own_sorting': own_sorting,
+                                      'other_sorting': other_sorting
+                                      })
 
 
 @signed_terms_required
@@ -793,8 +833,26 @@ def group_search(request, extra_context=None, **kwargs):
         if form.is_valid():
             q = form.cleaned_data['q'].strip()
     if q:
-        queryset = AstakosGroup.objects.select_related(
-        ).filter(name__contains=q)
+        queryset = AstakosGroup.objects.select_related()
+        queryset = queryset.filter(name__contains=q)
+        queryset = queryset.filter(approval_date__isnull=False)
+        queryset = queryset.extra(select={
+                'groupname': DB_REPLACE_GROUP_SCHEME,
+                'kindname': "im_groupkind.name",
+                'approved_members_num': """
+                    SELECT COUNT(*) FROM im_membership
+                    WHERE group_id = im_astakosgroup.group_ptr_id
+                    AND date_joined IS NOT NULL""",
+                'membership_approval_date': """
+                    SELECT date_joined FROM im_membership
+                    WHERE group_id = im_astakosgroup.group_ptr_id
+                    AND person_id = %s""" % request.user.id,
+                'is_member': """
+                    SELECT CASE WHEN EXISTS(
+                    SELECT date_joined FROM im_membership
+                    WHERE group_id = im_astakosgroup.group_ptr_id
+                    AND person_id = %s)
+                    THEN 1 ELSE 0 END""" % request.user.id})
     else:
         queryset = AstakosGroup.objects.none()
     return object_list(
@@ -810,9 +868,28 @@ def group_search(request, extra_context=None, **kwargs):
 @signed_terms_required
 @login_required
 def group_all(request, extra_context=None, **kwargs):
+    q = AstakosGroup.objects.select_related()
+    q = q.filter(approval_date__isnull=False)
+    q = q.extra(select={
+                'groupname': DB_REPLACE_GROUP_SCHEME,
+                'kindname': "im_groupkind.name",
+                'approved_members_num': """
+                    SELECT COUNT(*) FROM im_membership
+                    WHERE group_id = im_astakosgroup.group_ptr_id
+                    AND date_joined IS NOT NULL""",
+                'membership_approval_date': """
+                    SELECT date_joined FROM im_membership
+                    WHERE group_id = im_astakosgroup.group_ptr_id
+                    AND person_id = %s""" % request.user.id,
+                'is_member': """
+                    SELECT CASE WHEN EXISTS(
+                    SELECT date_joined FROM im_membership
+                    WHERE group_id = im_astakosgroup.group_ptr_id
+                    AND person_id = %s)
+                    THEN 1 ELSE 0 END""" % request.user.id})
     return object_list(
                 request,
-                AstakosGroup.objects.select_related().all(),
+                q,
                 paginate_by=PAGINATE_BY,
                 page=request.GET.get('page') or 1,
                 template_name='im/astakosgroup_list.html',
@@ -825,14 +902,12 @@ def group_all(request, extra_context=None, **kwargs):
 def group_join(request, group_id):
     m = Membership(group_id=group_id,
                    person=request.user,
-                   date_requested=datetime.now()
-                   )
+                   date_requested=datetime.now())
     try:
         m.save()
         post_save_redirect = reverse(
             'group_detail',
-            kwargs=dict(group_id=group_id)
-        )
+            kwargs=dict(group_id=group_id))
         return HttpResponseRedirect(post_save_redirect)
     except IntegrityError, e:
         logger.exception(e)
@@ -940,8 +1015,7 @@ def add_members(request, group_id):
                          object_id=group_id,
                          extra_context={'quota': group.quota,
                                         'form': form,
-                                        'search_form' : search_form}
-                         )
+                                        'search_form' : search_form})
 
 
 @signed_terms_required
@@ -1047,3 +1121,4 @@ def timeline(request):
                            form=form,
                            timeline_header=timeline_header,
                            timeline_body=timeline_body)
+                           l=l)