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

Add group_detail members table pagination

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