-#Mon Sep 10 11:32:44 EEST 2012
+#Thu Sep 27 13:01:48 EEST 2012
eclipse.preferences.version=1
+encoding//astakos/im/migrations/0010_auto__add_field_astakosuser_activation_sent__chg_field_service_url.py=utf-8
+encoding//astakos/im/migrations/0011_set_old_activation_sent.py=utf-8
encoding//astakos/im/migrations/0017_populate_resource_data.py=utf-8
+encoding//astakos/im/migrations/0023_populate_resource_data.py=utf-8
class AstakosGroupSortForm(forms.Form):
sort_by = forms.ChoiceField(label='Sort by',
- choices=(('groupname', 'Name'), ('kindname', 'Type')),
+ choices=(('groupname', 'Name'),
+ ('kindname', 'Type'),
+ ('issue_date', 'Issue Date'),
+ ('expiration_date', 'Expiration Date'),
+ ('approved_members_num', 'Participants'),
+ ('is_enabled', 'Status'),
+ ('moderation_enabled', 'Moderation'),
+ ('membership_status','Enrollment Status')
+ ),
+ required=False)
+
+class MembersSortForm(forms.Form):
+ sort_by = forms.ChoiceField(label='Sort by',
+ choices=(('person__email', 'User Id'),
+ ('person__first_name', 'Name'),
+ ('date_joined', 'Status')
+ ),
required=False)
'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):
@property
def members(self):
- return [m.person for m in self.membership_set.all()]
+ q = self.membership_set.select_related().all()
+ return [m.person for m in q]
@property
def approved_members(self):
- return [m.person for m in self.membership_set.all() if m.is_approved]
+ q = self.membership_set.select_related().all()
+ return [m.person for m in q if m.is_approved]
@property
def quota(self):
d = defaultdict(int)
- for q in self.astakosgroupquota_set.all():
+ for q in self.astakosgroupquota_set.select_related().all():
d[q.resource] += q.uplimit
return d
def owners(self):
return self.owner.all()
+ @property
+ def owner_details(self):
+ return self.owner.select_related().all()
+
@owners.setter
def owners(self, l):
self.owner = l
@property
def quota(self):
d = defaultdict(int)
- for q in self.astakosuserquota_set.all():
+ for q in self.astakosuserquota_set.select_related().all():
d[q.resource.name] += q.uplimit
- for m in self.membership_set.all():
+ for m in self.membership_set.select_related().all():
if not m.is_approved:
continue
g = m.group
AQUARIUM_URL = getattr(settings, 'ASTAKOS_AQUARIUM_URL', '')
# Set how many objects should be displayed per page
-PAGINATE_BY = getattr(settings, 'ASTAKOS_PAGINATE_BY', 10)
\ No newline at end of file
+PAGINATE_BY = getattr(settings, 'ASTAKOS_PAGINATE_BY', 8)
\ No newline at end of file
form.link-like { display:inline-block; margin:0 5px; float:right;}\r
form.link-like input[type="submit"] { margin:0; padding:0 5px; background:transparent; color:#F89A1C; cursor:pointer; height:auto; }\r
form.link-like input[type="submit"]:hover { text-decoration:underline; }\r
+form.link-like.alone { float:none; margin:0;}\r
+form.link-like.alone .form-row { margin:0; }\r
+form.link-like.alone input[type="submit"] { padding:0; } \r
.projects form.withlabels .checkbox-widget { margin-top:5px; }\r
.projects form .with-checkbox { margin:20px 0; }\r
.projects form .with-checkbox label { padding-top:7px; }\r
.details img { max-width:100%; }\r
.question .section { margin-top:1em; }\r
.question pre { border:1px dashed #000; padding:5px; margin:10px 0; line-height:auto; }\r
-.widjets { margin: 0; padding:0; }\r
+.widjets { position:relative; }\r
+.widjets ul { margin: 0; padding:0; }\r
.widjets li { width:50%; float:left; list-style:none outside; margin:30px 0; }\r
.widjets li div { border:1px dashed #000; padding:20px 20px 70px; width:60%; margin:0 auto; position:relative; }\r
.widjets li div img { max-width:100%; }\r
.widjets li .btn { text-align:center; position:absolute; bottom:0; left:0; right:0; }\r
+.widjets .widjet-x { position:absolute; right:0;top:0; font-weight:bold; font-size:1.5em; }\r
+.widjets .widjet-x:hover { text-decoration:none; color:#000; }\r
\r
/* billing styles */\r
.alt-style .table-div { border:1px dashed #000; }\r
$(this).hide();\r
})\r
\r
+ \r
+ $('.widjet-x').click(function(e){\r
+ e.preventDefault();\r
+ $(this).siblings('ul').hide('slow');\r
+ $(this).hide();\r
+ })\r
+ \r
});\r
\r
$(window).resize(function() {\r
{% load filters %}
{% block page.body %}
+{% with object.owners as owners %}
+{% with object.quota as quota %}
<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>
<dt>Name</dt>
<dd>{{object.name}} </dd>
<dt>Type</dt>
- <dd>{{object.kind|capfirst}} </dd>
+ <dd>{{object.kindname|capfirst}} </dd>
<dt>Issue date:</dt>
<dd>{{object.issue_date|date:"d/m/Y"}} </dd>
<dt>Expiration Date</dt>
<dt>Activated</dt>
<dd>{% if object.is_enabled %}Yes{% else %}No{% endif %}</dd>
<dt>Owner</dt>
- <dd>{% for o in object.owner.all %}
- {% if user == o %}
+ {{ o.owners }}
+ <dd>{% for o in owners %}
+ {% if object.is_owner %}
Me
{% else%}
{{o.realname}} ({{o.email}})
{% endif %}
</div>
<div class="full-dotted">
- {% if object.members %}
- <table class="alt-style table_sorting">
- <caption>MEMBERS:</caption>
- <thead>
- <tr>
- <th>User Id</th>
- <th>Name</th>
- <th>Status</th>
- </tr>
- </thead>
- <tbody>
- {% for m in object.membership_set.all %}
- <tr>
- <td>{{m.person.email}}</td>
- <td>{{m.person.realname}}</td>
- {% if m.person in m.group.owner.all %}
- <td>Owner</td>
- {% else %}
- {% if m.is_approved %}
- <td>Approved</td>
+ {% with page|concat:sorting as args %}
+ {% with object.membership_set.select_related.all|paginate:args as membership %}
+ {% if membership %}
+ <form method="GET" class="minimal" action="">
+ <div class="form-row">
+ <select name="sorting" onchange="this.form.submit();">
+ <option value="">Sort by</option>
+ <option value="person__email" {% if sorting == 'person__email' %}selected{% endif %}>User Id</option>
+ <option value="person__first_name" {% if sorting == 'person__first_name' %}selected{% endif %}>Name</option>
+ <option value="date_joined" {% if sorting == 'date_joined' %}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 m in membership.object_list %}
+ <tr>
+ <td>{{m.person.email}}</td>
+ <td>{{m.person.realname}}</td>
+ {% if m.person in owners %}
+ <td>Owner</td>
{% else %}
- <td>Pending
- {% if user in m.group.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 m.is_approved %}
+ <td>Approved</td>
+ {% else %}
+ <td>Pending
+ {% if object.is_owner %}
+ <a href="{% url approve_member object.id m.person.id %}?{% if page %}page={{ page }}{% endif %}{% if sorting %}&sorting={{sorting}}{% endif %}">Accept</a>
+ <a href="{% url disapprove_member object.id m.person.id %}?{% if page %}page={{ page }}{% endif %}{% if sorting %}&sorting={{sorting}}{% endif %}">Reject</a>
+ {% endif %}
+ </td>
{% endif %}
- </td>
{% endif %}
- {% endif %}
- </tr>
- {% endfor %}
- </tbody>
- </table>
- {% else %}
- <p>No members yet!</p>
- {% endif %}
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ <div class="pagination">
+ <p class="next-prev">
+ {% if membership.has_previous %}
+ <a href="?page={{ membership.previous_page_number }}{% if sorting %}&sorting={{sorting}}{% endif %}">previous</a>
+ {% endif %}
+ {% if membership.has_next %}
+ <a href="?page={{ membership.next_page_number }}{% if sorting %}&sorting={{sorting}}{% endif %}">next</a>
+ {% endif %}
+ </p>
+ <p class="nums">
+ <span class="current">
+ Page {{ membership.number }} of {{ membership.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">
</div>
+{% endwith %}
+{% endwith %}
{% endblock %}
{% block page.body %}
<div class="maincol {% block innerpage.class %}{% endblock %}">
- <h2>GROUPS</h2>
- {% if form %}
- <p>You can search for a group by name</p>
- <form action="{% url group_search %}" method="post" class="withlabels signup">{% csrf_token %}
- {% include "im/form_render.html" %}
- <div class="form-row submit">
- <input type="submit" class="submit altcol" value="SEARCH" />
- </div>
- </form>
-
- <form action="{% url group_all %}" method="post" class="link-like">{% csrf_token %}
- <div class="form-row submit">
- <input type="submit" class="submit altcol" value="Show all groups" />
- </div>
- </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>
-
- <ul class="widjets clearfix">
- <li>
- <div>
- <p>WELCOME!<br />Connect with a world of people who share your passions.<br />With millions of groups at your fingertips, it's easy to find the group that's best for you -- no matter your interest.</p>
- <p class="btn"><a href="{% url group_create_list %}" class="submit">CREATE</a></p>
- </div>
- </li>
- <li>
- <div>
- <p>LOOKING FOR A GROUP?</p><p>Well, this is the place to start!</br>sdofuisd ofuaofi usdiof uiofu osifuaoi ufisdfiousf oiusd<br /><img alt="THINK ABOUT IT" src="/static/medialibrary/2012/06/behind_okeanos.png"></p>
- <p class="btn"><a href="{% url group_search %}" class="submit">JOIN</a></p>
- </div>
- </li>
- </ul>-->
+ <h2>GROUPS</h2>
+ {% if form %}
+ <p>You can search for a group by name</p>
+ <form action="{% url group_search %}" method="post" class="withlabels signup">{% csrf_token %}
+ {% include "im/form_render.html" %}
+ <div class="form-row submit">
+ <input type="submit" class="submit altcol" value="SEARCH" />
+ </div>
+ </form>
+
+ <form action="{% url group_all %}" method="post" class="link-like alone">{% csrf_token %}
+ <div class="form-row submit">
+ <input type="submit" class="submit altcol" value="Show all groups" />
+ </div>
+ </form>
+ {% else %}
+
+ <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. <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>
+ <div class="widjets">
+ <a href="#" class="widjet-x" title="remove boxes">X</a>
+ <ul class="clearfix">
+ <li>
+ <div>
+ <p>WELCOME!<br>Connect with a world of people who share your passions.<br>With millions of groups at your fingertips, it's easy to find the group that's best for you -- no matter your interest.</p>
+ <p class="btn"><a href="{% url group_create_list %}" class="submit">CREATE</a></p>
+ </div>
+ </li>
+ <li>
+ <div>
+ <p>LOOKING FOR A GROUP?</p><p>Well, this is the place to start!<br>sdofuisd ofuaofi usdiof uiofu osifuaoi ufisdfiousf oiusd<br><img alt="THINK ABOUT IT" src="/static/medialibrary/2012/06/behind_okeanos.png"></p>
+ <p class="btn"><a href="{% url group_search %}" class="submit">JOIN</a></p>
+ </div>
+ </li>
+ </ul>
+ </div>
{% endif %}
{% with page_obj.object_list as object_list %}
+ <!-- Search group -->
{% if object_list %}
<div class="full-dotted">
+ <form method="GET" class="minimal" action="">
+ <div class="form-row">
+ <select name="sorting" onchange="this.form.submit();">
+ <option value="">Sort by</option>
+ <option value="groupname" {% if sorting == 'groupname' %}selected{% endif %}>Name</option>
+ <option value="kindname" {% if sorting == 'kindname' %}selected{% endif %}>Type</option>
+ <option value="issue_date" {% if sorting == 'issue_date' %}selected{% endif %}>Issue date</option>
+ <option value="expiration_date" {% if sorting == 'expiration_date' %}selected{% endif %}>Expiration Date</option>
+ <option value="approved_members_num" {% if sorting == 'approved_members_num' %}selected{% endif %}>Participants</option>
+ </select>
+ <input type="hidden" name="q" value="{{q}}"/>
+ </div>
+ </form>
<table class="alt-style complex">
<caption>
SEARCH RESULTS
{% if o.membership_approval_date %}
Registered
- <form action="{% url group_leave o.id %}" method="post" class="link-like">{% csrf_token %}
- <input type="submit" value="LEAVE GROUP" />
- </form>
+ {% if not o.is_owner %}
+ <form action="{% url group_leave o.id %}" method="post" class="link-like">{% csrf_token %}
+ <input type="submit" value="LEAVE GROUP" />
+ </form>
+ {% endif %}
<td><a href="#" class="more-info" title="more info"> </a></td>
</tr>
<tr class="{% cycle 'tmore1' 'tmore2' %}" style="display:none">
- <td colspan="8" class="info-td">
+ <td colspan="7" class="info-td">
<div>
<p>{{o.desc}}</p>
<p>{% if o.homepage%}
- Visit it group's home page: <a target="_blank" href="{{ o.homepage }}">{{ o.homepage }}</a>
- {% else %}
- There is no homepage for this group yet.
+ Group's home page: <a target="_blank" href="{{ o.homepage }}">{{ o.homepage }}</a>
+
{% endif %}
</p>
</div>
<div class="pagination">
<p class="next-prev">
{% if page_obj.has_previous %}
- <a href="?page={{ page_obj.previous_page_number }}{% if q %}&q={{q}}{% endif %}">previous</a>
+ <a href="?page={{ page_obj.previous_page_number }}{% if q %}&q={{q}}{% endif %}{% if sorting %}&sorting={{sorting}}{% endif %}">previous</a>
{% endif %}
{% if page_obj.has_next %}
- <a href="?page={{ page_obj.next_page_number }}{% if q %}&q={{q}}{% endif %}">next</a>
+ <a href="?page={{ page_obj.next_page_number }}{% if q %}&q={{q}}{% endif %}{% if sorting %}&sorting={{sorting}}{% endif %}">next</a>
{% endif %}
</p>
<p class="nums">
</span>
</p>
</div>
- {% else %}
- {% if mine %}
+ <!-- Group listing -->
+ {% else %}
+ {% if mine %}
+ {% with own_page|concat:own_sorting as args %}
+ {% with mine|paginate:args as 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>
+ <option value="kindname" {% if own_sorting == 'kindname' %}selected{% endif %}>Type</option>
+ <option value="issue_date" {% if own_sorting == 'issue_date' %}selected{% endif %}>Issue date</option>
+ <option value="expiration_date" {% if own_sorting == 'expiration_date' %}selected{% endif %}>Expiration Date</option>
+ <option value="approved_members_num" {% if own_sorting == 'approved_members_num' %}selected{% endif %}>Participants</option>
+ <option value="is_enabled" {% if own_sorting == 'is_enabled' %}selected{% endif %}>Status</option>
+ <option value="moderation_enabled" {% if own_sorting == 'moderation_enabled' %}selected{% endif %}>Moderation</option>
</select>
</div>
</form>
- <table class="alt-style complex" id="">
+ <table class="alt-style complex">
<caption>MY GROUPS</caption>
<thead>
<tr>
<div>
<p>{{o.desc}}</p>
<p>{% if o.homepage%}
- Visit it group's home page: <a href="{{ o.homepage }}">{{ o.homepage }}</a>
- {% else %}
- There is no homepage for this group yet.
+ Group's home page: <a href="{{ o.homepage }}">{{ o.homepage }}</a>
{% endif %}
</p>
</div>
</span>
</p>
</div>
-
+
+ {% endwith %}
+ {% endwith %}
{% endif %}
- {% if other %}
+
+ {% if other %}
+ {% with other_page|concat:other_sorting as args %}
+ {% with other|paginate:args as other %}
<div class="full-dotted">
<form method="GET" class="minimal" action="">
<div class="form-row">
<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>
+ <option value="issue_date" {% if other_sorting == 'issue_date' %}selected{% endif %}>Issue date</option>
+ <option value="expiration_date" {% if other_sorting == 'expiration_date' %}selected{% endif %}>Expiration Date</option>
+ <option value="approved_members_num" {% if other_sorting == 'approved_members_num' %}selected{% endif %}>Participants</option>
+ <option value="membership_status" {% if other_sorting == 'membership_status' %}selected{% endif %}>Enrollment Status</option>
+
</select>
</div>
</form>
<th>Type</th>
<th>Issued</th>
<th>Expires</th>
+
<th>Enrolled</th>
<td>{{ o.approved_members_num }}</td>
<td>
- {% if o.membership_approval_date %}
-
- Registered
+ {% if o.membership_status %}
+ Registered
<form action="{% url group_leave o.id %}" method="post" class="link-like">{% csrf_token %}
<input type="submit" value="LEAVE GROUP" />
</form>
-
{% else %}
Pending
{% endif %}
<td><a href="#" class="more-info" title="more info"> </a></td>
</tr>
<tr class="{% cycle 'tmore1' 'tmore2' %}" style="display:none">
- <td colspan="8" class="info-td">
+ <td colspan="7" class="info-td">
<div>
<p>{{o.desc}}</p>
<p>{% if o.homepage%}
</span>
</p>
</div>
-
+
+ {% endwith %}
+ {% endwith %}
{% endif %}
+
{% if q %}
<h2>No groups found!</h2>
{% endif %}
{% block page.body %}
<div class="maincol {% block innerpage.class %}{% endblock %}">
<div class="section">
- {% if quota %}
- <table class="zebra-striped id-sorted">
- <thead>
- <tr>
- <th>Resource</th>
- <th>Limit</th>
- </tr>
- </thead>
- <tbody>
- {% for k in quota|dkeys %}
- <tr>
- <td>{{ k }}</td>
- <td>{{ quota|lookup:k }}</td>
- </tr>
+ {% for k, v in user.quota|items %}
+ <strong>{{k}}</strong>
+ <table class="zebra-striped id-sorted">
+<!--
+ <thead>
+ <tr>
+ <th>Limit (Group)</th>
+ </tr>
+ </thead>
+ -->
+ <tbody>
+ {% for m in user.membership_set.select_related.all %}
+ {% if m.group.is_enabled %}
+ {% with m.group.quota as quota %}
+ {% if quota %}
+ {% for kk, vv in quota|items %}
+ {% if k == kk %}
+ <tr>
+ <td>{{ vv }} ({{m.group.name}})</td>
+ </tr>
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+ {% endwith %}
+ {% endif %}
+ {% endfor %}
+ <tr>
+ <td><strong>{{ v }}</strong></td>
+ </tr>
+ <tr/>
+ </tbody>
+ </table>
{% endfor %}
- </tbody>
- </table>
- {% else %}
- <p>No policies</p>
- {% endif %}
</div>
</div>
{% endblock %}
import calendar
import datetime
+from collections import defaultdict
+
from django import template
+from django.core.paginator import Paginator, EmptyPage
+from django.db.models.query import QuerySet
from astakos.im.settings import PAGINATE_BY
register = template.Library()
+DELIM = ','
+
@register.filter
def monthssince(joined_date):
now = datetime.datetime.now()
@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:
+ if isinstance(l, QuerySet):
+ l = l.order_by(sorting)
+ elif isinstance(l, list):
+ default = ''
+ if sorting.endswith('_date'):
+ default = datetime.datetime.utcfromtimestamp(0)
+ l.sort(key=lambda i: getattr(i, sorting) \
+ if getattr(i, sorting) else default)
+
+ paginator = Paginator(l, PAGINATE_BY)
+
+ try:
+ page_number = int(page)
+ except ValueError:
+ if page == 'last':
+ page_number = paginator.num_pages
+ else:
+ page_number = 1
+ try:
+ page = paginator.page(page_number)
+ except EmptyPage:
+ page = paginator.page(1)
+ return page
+
+@register.filter
+def concat(str1, str2):
+ if not str2:
+ return str(str1)
+ return '%s%s%s' % (str1, DELIM, str2)
+
+@register.filter
+def items(d):
+ if isinstance(d, defaultdict):
+ return d.iteritems()
+ return d
\ No newline at end of file
'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/?$',
'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'),
)
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,
get_model_and_form_class)
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,
ExtendedPasswordChangeForm, EmailChangeForm,
AstakosGroupCreationForm, AstakosGroupSearchForm,
AstakosGroupUpdateForm, AddGroupMembersForm,
- AstakosGroupSortForm, TimelineForm)
+ AstakosGroupSortForm, MembersSortForm,
+ TimelineForm)
from astakos.im.functions import (send_feedback, SendMailError,
invite as invite_func, logout as auth_logout,
activate as activate_func,
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:
return response
messages.success(request, _('You have successfully logged out.'))
context = get_context(request, extra_context)
- response.write(loader.render_to_string(template, context_instance=context))
+ response.write(template_loader.render_to_string(template, context_instance=context))
return response
@transaction.commit_manually
-def activate(request, greeting_email_template_name='im/welcome_email.txt', helpdesk_email_template_name='im/helpdesk_notification.txt'):
+def activate(request, greeting_email_template_name='im/welcome_email.txt',
+ helpdesk_email_template_name='im/helpdesk_notification.txt'):
"""
Activates the user identified by the ``auth`` request parameter, sends a welcome email
and renews the user token.
except:
return HttpResponseBadRequest(_('No such group kind'))
- template_loader = loader
post_save_redirect = '/im/group/%(id)s/'
context_processors = None
model, form_class = get_model_and_form_class(
(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
+ (SELECT CASE WHEN(
+ SELECT date_joined FROM im_membership
+ WHERE group_id = im_astakosgroup.group_ptr_id
+ AND person_id = %s) IS NULL
+ THEN 0 ELSE 1 END) AS membership_status
FROM im_astakosgroup
INNER JOIN im_membership ON (
im_astakosgroup.group_ptr_id = im_membership.group_id)
d['own'].append(g)
else:
d['other'].append(g)
- d.setdefault('own', [])
- d.setdefault('other', [])
- 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:
- if page == 'last':
- page_number = paginator.num_pages
- else:
- # Page is not 'last', nor can it be converted to an int.
- raise Http404
- try:
- page_obj = globals()['%s_page_obj' % k] = paginator.page(page_number)
- except InvalidPage:
- raise Http404
+
+ # validate sorting
+ fields = ('own', 'other')
+ for f in fields:
+ v = globals()['%s_sorting' % f] = request.GET.get('%s_sorting' % f)
+ if v:
+ form = AstakosGroupSortForm({'sort_by': v})
+ if not form.is_valid():
+ globals()['%s_sorting' % f] = form.cleaned_data.get('sort_by')
return object_list(request, queryset=none,
extra_context={'is_search':False,
- 'mine': own_page_obj,
- 'other': other_page_obj,
+ 'mine': d['own'],
+ 'other': d['other'],
'own_sorting': own_sorting,
- 'other_sorting': other_sorting
+ 'other_sorting': other_sorting,
+ 'own_page': request.GET.get('own_page', 1),
+ 'other_page': request.GET.get('other_page', 1)
})
@signed_terms_required
@login_required
def group_detail(request, group_id):
+ q = AstakosGroup.objects.select_related().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)
+ obj = q.get()
except AstakosGroup.DoesNotExist:
- return HttpResponseBadRequest(_('Invalid group.'))
- form = AstakosGroupUpdateForm(instance=group)
- 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}
- )
+ raise Http404("No %s found matching the query" % (
+ model._meta.verbose_name))
+
+ 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()
+
+ 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)
+
+ # validate sorting
+ sorting= request.GET.get('sorting')
+ if sorting:
+ form = MembersSortForm({'sort_by': sorting})
+ if form.is_valid():
+ sorting = form.cleaned_data.get('sort_by')
+
+ extra_context = {'update_form': update_form,
+ 'addmembers_form': addmembers_form,
+ 'page': request.GET.get('page', 1),
+ 'sorting': sorting}
+ for key, value in extra_context.items():
+ if callable(value):
+ c[key] = value()
+ else:
+ 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
def group_search(request, extra_context=None, **kwargs):
q = request.GET.get('q')
+ sorting = request.GET.get('sorting')
if request.method == 'GET':
form = AstakosGroupSearchForm({'q': q} if q else None)
else:
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,
+ '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})
+ if sorting:
+ # TODO check sorting value
+ queryset = queryset.order_by(sorting)
else:
queryset = AstakosGroup.objects.none()
return object_list(
template_name='im/astakosgroup_list.html',
extra_context=dict(form=form,
is_search=True,
- q=q))
+ q=q,
+ sorting=sorting))
@signed_terms_required
@login_required
WHERE group_id = im_astakosgroup.group_ptr_id
AND person_id = %s)
THEN 1 ELSE 0 END""" % request.user.id})
+ sorting = request.GET.get('sorting')
+ if sorting:
+ # TODO check sorting value
+ q = q.order_by(sorting)
return object_list(
request,
q,
page=request.GET.get('page') or 1,
template_name='im/astakosgroup_list.html',
extra_context=dict(form=AstakosGroupSearchForm(),
- is_search=True))
+ is_search=True,
+ sorting=sorting))
@signed_terms_required
try:
m = Membership.objects.select_related().get(
group__id=group_id,
- person=request.user
- )
+ person=request.user)
except Membership.DoesNotExist:
return HttpResponseBadRequest(_('Invalid membership.'))
if request.user in m.group.owner.all():
template_name='im/astakosgroup_list.html',
post_delete_redirect=reverse(
'group_detail',
- kwargs=dict(group_id=group_id)
- )
- )
+ kwargs=dict(group_id=group_id)))
def handle_membership(func):
try:
m = Membership.objects.select_related().get(
group__id=group_id,
- person__id=user_id
- )
+ person__id=user_id)
except Membership.DoesNotExist:
return HttpResponseBadRequest(_('Invalid membership.'))
else:
if request.user not in m.group.owner.all():
return HttpResponseForbidden(_('User is not a group owner.'))
func(request, m)
- return render_response(
- template='im/astakosgroup_detail.html',
- context_instance=get_context(request),
- object=m.group,
- quota=m.group.quota
- )
+ return group_detail(request, group_id)
return wrapper
messages.success(request, msg)
except BaseException, e:
logger.exception(e)
+ realname = membership.person.realname
msg = _('Something went wrong during %s\'s approval.' % realname)
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
@login_required
def resource_list(request):
return render_response(
template='im/astakosuserquota_list.html',
- context_instance=get_context(request),
- quota=request.user.quota
- )
+ context_instance=get_context(request))
def group_create_list(request):
return render_response(
template='im/astakosgroup_create_list.html',
- context_instance=get_context(request),
- )
+ context_instance=get_context(request),)
@signed_terms_required
try:
status, data = r.result
- data=clear_billing_data(data)
+ data=_clear_billing_data(data)
if status != 200:
messages.error(request, _('Service response status: %d' % status))
except:
start=int(start),
month_last_day=month_last_day)
-def clear_billing_data(data):
+def _clear_billing_data(data):
# remove addcredits entries
def isnotcredit(e):
form=form,
timeline_header=timeline_header,
timeline_body=timeline_body)
+ return data