Commit b1075008 authored by Sofia Papagiannaki's avatar Sofia Papagiannaki
Browse files

Merge branch '0.6.4' into dev

Conflicts:
	snf-astakos-app/astakos/im/forms.py
	snf-astakos-app/astakos/im/views.py
parents 4b05cdfd a6fb45e6
......@@ -615,3 +615,8 @@ class TimelineForm(forms.Form):
if 'end_date' in d:
d['end_date'] = d['end_date'].strftime("%%Y-%m-%dT%H:%M:%S.%f")
return d
class AstakosGroupSortForm(forms.Form):
sort_by = forms.ChoiceField(label='Sort by',
choices=(('groupname', 'Name'), ('kindname', 'Type')),
required=False)
\ No newline at end of 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()
......
......@@ -156,7 +156,9 @@ form.link-like input[type="submit"]:hover { text-decoration:underline; }
.projects form .with-checkbox { margin:20px 0; }
.projects form .with-checkbox label { padding-top:7px; }
.projects form .with-checkbox span.info { bottom:24px; }
.projects .minimal { float:right; position:relative; margin-bottom:-20px;}
.projects .minimal select { padding:3px; width:250px; }
.projects .minimal label { position:absolute; right:290px; top:5px; white-space:nowrap}
@media screen and (max-width : 630px) {
form.withlabels .extra-img { left:260px; }
......
......@@ -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>
......@@ -36,19 +36,15 @@
<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>
......@@ -67,16 +63,16 @@
</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 %}
......@@ -84,16 +80,16 @@
</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>
......@@ -103,7 +99,7 @@
<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 %}
......@@ -116,24 +112,35 @@
</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>
......@@ -152,11 +159,11 @@
<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>
......@@ -179,30 +186,36 @@
</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>
......@@ -222,15 +235,15 @@
<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 %}
......@@ -239,15 +252,7 @@
{% 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>
......@@ -271,20 +276,21 @@
</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>
......
......@@ -75,13 +75,6 @@ def dkeys(d):
return d.keys()
@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
......@@ -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,
......@@ -83,6 +84,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):
"""
......@@ -717,14 +721,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:
......@@ -734,13 +771,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
......@@ -792,8 +832,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(
......@@ -809,9 +867,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',
......@@ -824,14 +901,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)
......@@ -939,8 +1014,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
......@@ -1050,4 +1124,4 @@ def timeline(request):
return render_response(template='im/timeline.html',
context_instance=get_context(request),
form=form,
l=l)
\ No newline at end of file
l=l)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment