Revision d220292f
b/snf-astakos-app/README | ||
---|---|---|
84 | 84 |
ASTAKOS_SERVICES {'cyclades': {'url':'https://node1.example.com/ui/', 'quota': {'vm': 2}}, Cloud service default url and quota |
85 | 85 |
'pithos+': {'url':'https://node2.example.com/ui/', 'quota': { |
86 | 86 |
'diskspace': 50 * 1024 * 1024 * 1024}}}) |
87 |
AQUARIUM_URL '' The billing (aquarium) URI
|
|
87 |
ASTAKOS_AQUARIUM_URL '' The billing (aquarium) URI
|
|
88 | 88 |
e.g. ``http://localhost:8888/user`` |
89 |
ASTAKOS_PAGINATE_BY 10 Number of object to be displayed per page |
|
89 | 90 |
=================================== ============================================================================= =========================================================================================== |
90 | 91 |
|
91 | 92 |
Administrator functions |
b/snf-astakos-app/astakos/im/settings.py | ||
---|---|---|
133 | 133 |
PASSWORD_RESET_EMAIL_SUBJECT = getattr(settings, 'ASTAKOS_PASSWORD_RESET_EMAIL_SUBJECT', |
134 | 134 |
'Password reset on %s alpha2 testing' % SITENAME) |
135 | 135 |
|
136 |
# Set how many objects should be displayed per page |
|
137 |
PAGINATE_BY = getattr(settings, 'ASTAKOS_PAGINATE_BY', 10) |
b/snf-astakos-app/astakos/im/templates/im/astakosgroup_list.html | ||
---|---|---|
39 | 39 |
</ul> |
40 | 40 |
|
41 | 41 |
{% endif %} |
42 |
{% with object_list|enabled:is_search as object_list %} |
|
42 |
{% with page_obj.object_list|enabled:is_search as object_list %}
|
|
43 | 43 |
{% if object_list %} |
44 |
{% with object_list|split:user as d %} |
|
45 |
{% with d|lookup:'own' as mine %} |
|
46 |
{% if mine %} |
|
47 |
<div class="full-dotted"> |
|
44 |
<div class="full-dotted"> |
|
45 |
<table class="alt-style complex"> |
|
46 |
<caption> |
|
47 |
{% if is_search %} |
|
48 |
SEARCH RESULTS |
|
49 |
{% else %} |
|
50 |
I PARTICIPATE IN |
|
51 |
{% endif %} |
|
52 |
</caption> |
|
53 |
<thead> |
|
54 |
<tr> |
|
55 |
<th>Name</th> |
|
56 |
<th>Type</th> |
|
57 |
<th>Issued</th> |
|
58 |
<th>Expires</th> |
|
59 |
|
|
60 |
<th>Enrolled</th> |
|
61 |
|
|
62 |
|
|
63 |
<th>Enrollment status</th> |
|
64 |
<th> </th> |
|
65 |
|
|
66 |
</tr> |
|
67 |
</thead> |
|
68 |
<tbody> |
|
69 |
{% for o in object_list %} |
|
70 |
<tr class="{% cycle 'tr1' 'tr2' %}"> |
|
71 |
<td><a href="{% url group_detail o.id %}" title="visit group page">{{o.name|cut:"http://"|cut:"/" }}</a></td> |
|
72 |
<td>{{o.kind|capfirst}}</td> |
|
73 |
<td>{{o.issue_date|date:"d/m/Y"}}</td> |
|
74 |
<td>{{o.expiration_date|date:"d/m/Y"}}</td> |
|
75 |
|
|
76 |
<td>{{ o.approved_members|length }}</td> |
|
77 |
|
|
78 |
<td> |
|
79 |
{% if user in o.approved_members %} |
|
80 |
|
|
81 |
Registered |
|
82 |
<form action="{% url group_leave o.id %}" method="post" class="link-like">{% csrf_token %} |
|
83 |
<input type="submit" value="LEAVE GROUP" /> |
|
84 |
</form> |
|
85 |
|
|
86 |
|
|
87 |
{% else %} |
|
88 |
{% if user in o.members %} |
|
89 |
Pending |
|
90 |
{% else %} |
|
91 |
Not member |
|
92 |
<form action="{% url group_join o.id %}" method="post" class="link-like">{% csrf_token %} |
|
93 |
<input type="submit" value="JOIN GROUP" /> |
|
94 |
</form> |
|
95 |
|
|
96 |
{% endif %} |
|
97 |
{% endif %} |
|
98 |
</td> |
|
99 |
<td><a href="#" class="more-info" title="more info"> </a></td> |
|
100 |
</tr> |
|
101 |
<tr class="{% cycle 'tmore1' 'tmore2' %}" style="display:none"> |
|
102 |
<td colspan="8" class="info-td"> |
|
103 |
<div> |
|
104 |
<p>{{o.desc}}</p> |
|
105 |
<p>{% if o.homepage%} |
|
106 |
Visit it group's home page: <a href="{{ o.homepage }}">{{ o.homepage }}</a> |
|
107 |
{% else %} |
|
108 |
There is no homepage for this group yet. |
|
109 |
{% endif %} |
|
110 |
</p> |
|
111 |
</div> |
|
112 |
</td> |
|
113 |
</tr> |
|
114 |
{% endfor %} |
|
115 |
</tbody> |
|
116 |
</table> |
|
117 |
|
|
118 |
</div> |
|
119 |
<div class="pagination"> |
|
120 |
<span class="step-links"> |
|
121 |
{% if page_obj.has_previous %} |
|
122 |
<a href="?page={{ page_obj.previous_page_number }}{% if q %}&q={{q}}{% endif %}">previous</a> |
|
123 |
{% endif %} |
|
124 |
|
|
125 |
<span class="current"> |
|
126 |
Page {{ page_obj.number }} of {{ paginator.num_pages }}. |
|
127 |
</span> |
|
128 |
|
|
129 |
{% if page_obj.has_next %} |
|
130 |
<a href="?page={{ page_obj.next_page_number }}{% if q %}&q={{q}}{% endif %}">next</a> |
|
131 |
{% endif %} |
|
132 |
</span> |
|
133 |
</div> |
|
134 |
{% else %} |
|
135 |
{% if mine %} |
|
136 |
<div class="full-dotted"> |
|
48 | 137 |
<table class="alt-style complex" id=""> |
49 | 138 |
<caption>MY GROUPS</caption> |
50 | 139 |
<thead> |
... | ... | |
61 | 150 |
</tr> |
62 | 151 |
</thead> |
63 | 152 |
<tbody> |
64 |
{% for o in mine %} |
|
153 |
{% for o in mine.object_list %}
|
|
65 | 154 |
<tr class="{% cycle 'tr1' 'tr2' %}"> |
66 | 155 |
<td><a href="{% url group_detail o.id %}" title="visit group page">{{o.name|cut:"http://"|cut:"/" }}</a></td> |
67 | 156 |
<td>{{o.kind|capfirst}}</td> |
... | ... | |
77 | 166 |
<div> |
78 | 167 |
<p>{{o.desc}}</p> |
79 | 168 |
<p>{% if o.homepage%} |
80 |
Vistit group's home page: <a href="{{ o.homepage }}">{{ o.homepage }}</a>
|
|
169 |
Visit it group's home page: <a href="{{ o.homepage }}">{{ o.homepage }}</a>
|
|
81 | 170 |
{% else %} |
82 | 171 |
There is no homepage for this group yet. |
83 | 172 |
{% endif %} |
... | ... | |
88 | 177 |
{% endfor %} |
89 | 178 |
</tbody> |
90 | 179 |
</table> |
91 |
|
|
92 | 180 |
</div> |
181 |
<div class="pagination"> |
|
182 |
<span class="step-links"> |
|
183 |
{% if mine.has_previous %} |
|
184 |
<a href="?own_page={{ mine.previous_page_number }}">previous</a> |
|
185 |
{% endif %} |
|
186 |
|
|
187 |
<span class="current"> |
|
188 |
Page {{ mine.number }} of {{ mine.paginator.num_pages }}. |
|
189 |
</span> |
|
190 |
|
|
191 |
{% if mine.has_next %} |
|
192 |
<a href="?own_page={{ mine.next_page_number }}">next</a> |
|
193 |
{% endif %} |
|
194 |
</span> |
|
195 |
</div> |
|
93 | 196 |
{% endif %} |
94 |
{% endwith %} |
|
95 |
{% with d|lookup:'other' as other %} |
|
96 | 197 |
{% if other %} |
97 |
<div class="full-dotted"> |
|
198 |
<div class="full-dotted">
|
|
98 | 199 |
<table class="alt-style complex"> |
99 | 200 |
<caption> |
100 | 201 |
{% if is_search %} |
... | ... | |
119 | 220 |
</tr> |
120 | 221 |
</thead> |
121 | 222 |
<tbody> |
122 |
{% for o in other %} |
|
223 |
{% for o in other.object_list %}
|
|
123 | 224 |
<tr class="{% cycle 'tr1' 'tr2' %}"> |
124 | 225 |
<td><a href="{% url group_detail o.id %}" title="visit group page">{{o.name|cut:"http://"|cut:"/" }}</a></td> |
125 | 226 |
<td>{{o.kind|capfirst}}</td> |
... | ... | |
156 | 257 |
<div> |
157 | 258 |
<p>{{o.desc}}</p> |
158 | 259 |
<p>{% if o.homepage%} |
159 |
Vistit group's home page: <a href="{{ o.homepage }}">{{ o.homepage }}</a>
|
|
260 |
Visit it group's home page: <a href="{{ o.homepage }}">{{ o.homepage }}</a>
|
|
160 | 261 |
{% else %} |
161 | 262 |
There is no homepage for this group yet. |
162 | 263 |
{% endif %} |
... | ... | |
169 | 270 |
</table> |
170 | 271 |
|
171 | 272 |
</div> |
273 |
<div class="pagination"> |
|
274 |
<span class="step-links"> |
|
275 |
{% if other.has_previous %} |
|
276 |
<a href="?other_page={{ other.previous_page_number }}">previous</a> |
|
277 |
{% endif %} |
|
278 |
|
|
279 |
<span class="current"> |
|
280 |
Page {{ other.number }} of {{ other.paginator.num_pages }}. |
|
281 |
</span> |
|
282 |
|
|
283 |
{% if other.has_next %} |
|
284 |
<a href="?other_page={{ other.next_page_number }}">next</a> |
|
285 |
{% endif %} |
|
286 |
</span> |
|
287 |
</div> |
|
172 | 288 |
{% endif %} |
173 |
{% endwith %} |
|
174 |
{% endwith %} |
|
175 |
{% else %} |
|
176 |
{% if is_search %} |
|
289 |
{% if q %} |
|
177 | 290 |
<h2>No groups found!</h2> |
178 | 291 |
{% endif %} |
179 | 292 |
{% endif %} |
b/snf-astakos-app/astakos/im/templatetags/filters.py | ||
---|---|---|
31 | 31 |
# interpreted as representing official policies, either expressed |
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 |
from django import template |
|
35 | 34 |
import calendar |
36 | 35 |
import datetime |
37 | 36 |
|
37 |
from django import template |
|
38 |
|
|
39 |
from astakos.im.settings import PAGINATE_BY |
|
40 |
|
|
38 | 41 |
register = template.Library() |
39 | 42 |
|
40 | 43 |
@register.filter |
... | ... | |
80 | 83 |
|
81 | 84 |
|
82 | 85 |
@register.filter |
83 |
def split(object_list, user): |
|
84 |
try: |
|
85 |
d = {} |
|
86 |
d['own'] = [g for g in object_list if user in g.owner.all()] |
|
87 |
d['other'] = list(set(object_list) - set(d['own'])) |
|
88 |
return d |
|
89 |
except: |
|
90 |
return {'own': object_list, 'other': ()} |
|
91 |
|
|
92 |
|
|
93 |
@register.filter |
|
94 | 86 |
def month_name(month_number): |
95 | 87 |
return calendar.month_name[month_number] |
96 | 88 |
|
... | ... | |
98 | 90 |
@register.filter |
99 | 91 |
def todate(value, arg = ''): |
100 | 92 |
secs = int(value) / 1000 |
101 |
return datetime.datetime.fromtimestamp(secs) |
|
93 |
return datetime.datetime.fromtimestamp(secs) |
b/snf-astakos-app/astakos/im/views.py | ||
---|---|---|
56 | 56 |
get_model_and_form_class) |
57 | 57 |
from django.views.generic.list_detail import object_list, object_detail |
58 | 58 |
from django.http import HttpResponseBadRequest |
59 |
from django.core.paginator import Paginator, InvalidPage |
|
59 | 60 |
|
60 | 61 |
from astakos.im.models import ( |
61 | 62 |
AstakosUser, ApprovalTerms, AstakosGroup, Resource, |
... | ... | |
75 | 76 |
SendNotificationError) |
76 | 77 |
from astakos.im.settings import ( |
77 | 78 |
COOKIE_NAME, COOKIE_DOMAIN, SITENAME, LOGOUT_NEXT, |
78 |
LOGGING_LEVEL |
|
79 |
) |
|
79 |
LOGGING_LEVEL, PAGINATE_BY) |
|
80 | 80 |
from astakos.im.tasks import request_billing |
81 | 81 |
|
82 | 82 |
logger = logging.getLogger(__name__) |
... | ... | |
716 | 716 |
@signed_terms_required |
717 | 717 |
@login_required |
718 | 718 |
def group_list(request): |
719 |
q = request.user.astakos_groups.none() |
|
719 | 720 |
list = request.user.astakos_groups.select_related().all() |
720 |
return object_list(request, queryset=list, |
|
721 |
extra_context=dict( |
|
722 |
is_search=False |
|
723 |
) |
|
724 |
) |
|
721 |
d = {} |
|
722 |
d['own'] = [g for g in list if request.user in g.owner.all()] |
|
723 |
d['other'] = list.exclude(id__in=(g.id for g in d['own'])) |
|
724 |
for k, queryset in d.iteritems(): |
|
725 |
paginator = Paginator(queryset, PAGINATE_BY) |
|
726 |
page = request.GET.get('%s_page' % k, 1) |
|
727 |
try: |
|
728 |
page_number = int(page) |
|
729 |
except ValueError: |
|
730 |
if page == 'last': |
|
731 |
page_number = paginator.num_pages |
|
732 |
else: |
|
733 |
# Page is not 'last', nor can it be converted to an int. |
|
734 |
raise Http404 |
|
735 |
try: |
|
736 |
page_obj = locals()['%s_page_obj' % k] = paginator.page(page_number) |
|
737 |
except InvalidPage: |
|
738 |
raise Http404 |
|
739 |
return object_list(request, queryset=q, |
|
740 |
extra_context={'is_search':False, |
|
741 |
'mine': locals()['own_page_obj'], |
|
742 |
'other': locals()['other_page_obj']}) |
|
725 | 743 |
|
726 | 744 |
|
727 | 745 |
@signed_terms_required |
... | ... | |
765 | 783 |
@signed_terms_required |
766 | 784 |
@login_required |
767 | 785 |
def group_search(request, extra_context=None, **kwargs): |
786 |
q = request.GET.get('q') |
|
768 | 787 |
if request.method == 'GET': |
769 |
form = AstakosGroupSearchForm() |
|
788 |
form = AstakosGroupSearchForm({'q': q} if q else None)
|
|
770 | 789 |
else: |
771 | 790 |
form = AstakosGroupSearchForm(get_query(request)) |
772 | 791 |
if form.is_valid(): |
773 | 792 |
q = form.cleaned_data['q'].strip() |
774 |
queryset = AstakosGroup.objects.select_related(
|
|
775 |
).filter(name__contains=q)
|
|
776 |
return object_list(
|
|
777 |
request,
|
|
778 |
queryset,
|
|
779 |
template_name='im/astakosgroup_list.html',
|
|
780 |
extra_context=dict(form=form,
|
|
781 |
is_search=True))
|
|
782 |
return render_response(
|
|
783 |
template='im/astakosgroup_list.html',
|
|
784 |
form=form,
|
|
785 |
context_instance=get_context(request, extra_context),
|
|
786 |
is_search=False
|
|
787 |
) |
|
793 |
if q:
|
|
794 |
queryset = AstakosGroup.objects.select_related(
|
|
795 |
).filter(name__contains=q)
|
|
796 |
else:
|
|
797 |
queryset = AstakosGroup.objects.none()
|
|
798 |
return object_list(
|
|
799 |
request,
|
|
800 |
queryset,
|
|
801 |
paginate_by=PAGINATE_BY,
|
|
802 |
page=request.GET.get('page') or 1,
|
|
803 |
template_name='im/astakosgroup_list.html',
|
|
804 |
extra_context=dict(form=form,
|
|
805 |
is_search=True,
|
|
806 |
q=q))
|
|
788 | 807 |
|
789 | 808 |
@signed_terms_required |
790 | 809 |
@login_required |
791 | 810 |
def group_all(request, extra_context=None, **kwargs): |
792 |
if request.method != 'POST': |
|
793 |
return HttpResponseBadRequest(_('Bad method')) |
|
794 | 811 |
return object_list( |
795 | 812 |
request, |
796 | 813 |
AstakosGroup.objects.select_related().all(), |
814 |
paginate_by=PAGINATE_BY, |
|
815 |
page=request.GET.get('page') or 1, |
|
797 | 816 |
template_name='im/astakosgroup_list.html', |
798 | 817 |
extra_context=dict(form=AstakosGroupSearchForm(), |
799 | 818 |
is_search=True)) |
b/snf-astakos-app/conf/20-snf-astakos-app-settings.conf | ||
---|---|---|
122 | 122 |
#ASTAKOS_ADMIN_NOTIFICATION_EMAIL_SUBJECT = '%s alpha2 testing account created (%%(user)s)' % SITENAME |
123 | 123 |
#ASTAKOS_HELPDESK_NOTIFICATION_EMAIL_SUBJECT = '%s alpha2 testing account activated (%%(user)s)' % SITENAME |
124 | 124 |
#ASTAKOS_EMAIL_CHANGE_EMAIL_SUBJECT = 'Email change on %s alpha2 testing' % SITENAME |
125 |
#ASTAKOS_PASSWORD_RESET_EMAIL_SUBJECT = 'Password reset on %s alpha2 testing' % SITENAME |
|
125 |
#ASTAKOS_PASSWORD_RESET_EMAIL_SUBJECT = 'Password reset on %s alpha2 testing' % SITENAME |
|
126 |
|
|
127 |
# Set how many objects should be displayed per page |
|
128 |
#PAGINATE_BY = getattr(settings, 'ASTAKOS_PAGINATE_BY', 10) |
Also available in: Unified diff