Revision 0dadf7b2
b/pithos/im/templates/base.html | ||
---|---|---|
22 | 22 |
<li{% ifequal tab "users" %} class="active"{% endifequal %}> |
23 | 23 |
<a href="{% url pithos.im.views.users_list %}">Users</a> |
24 | 24 |
</li> |
25 |
<li{% ifequal tab "invitations" %} class="active"{% endifequal %}> |
|
26 |
<a href="{% url pithos.im.views.invitations_list %}">Invitations</a> |
|
27 |
</li> |
|
25 | 28 |
</ul> |
26 | 29 |
|
27 | 30 |
{% block body %}{% endblock %} |
b/pithos/im/templates/invitations_list.html | ||
---|---|---|
1 |
{% extends "base.html" %} |
|
2 |
|
|
3 |
{% load formatters %} |
|
4 |
|
|
5 |
{% block body %} |
|
6 |
|
|
7 |
<div class="row"> |
|
8 |
<div class="offset10 span3"> |
|
9 |
<form method="get"> |
|
10 |
<div class="input"> |
|
11 |
<input class="span3" name="filter" type="search" placeholder="search" value="{{ filter }}"> |
|
12 |
</div> |
|
13 |
</form> |
|
14 |
</div> |
|
15 |
</div> |
|
16 |
|
|
17 |
<table class="zebra-striped id-sorted"> |
|
18 |
<thead> |
|
19 |
<tr> |
|
20 |
<th>ID</th> |
|
21 |
<th>Uniq</th> |
|
22 |
<th>Real Name</th> |
|
23 |
<th>Code</th> |
|
24 |
<th>Inviter Uniq</th> |
|
25 |
<th>Inviter Real Name</th> |
|
26 |
<th>Is_accepted</th> |
|
27 |
<th>Created</th> |
|
28 |
<th>Accepted</th> |
|
29 |
</tr> |
|
30 |
</thead> |
|
31 |
<tbody> |
|
32 |
{% for inv in invitations %} |
|
33 |
<tr> |
|
34 |
<td>{{ inv.id }}</td> |
|
35 |
<td>{{ inv.uniq }}</td> |
|
36 |
<td>{{ inv.realname }}</td> |
|
37 |
<td>{{ inv.code }}</td> |
|
38 |
<td>{{ inv.inviter.uniq }}</td> |
|
39 |
<td>{{ inv.inviter.realname }}</td> |
|
40 |
<td>{{ inv.is_accepted }}</td> |
|
41 |
<td>{{ inv.created }}</td> |
|
42 |
<td>{{ inv.accepted }}</td> |
|
43 |
</tr> |
|
44 |
{% endfor %} |
|
45 |
</tbody> |
|
46 |
</table> |
|
47 |
|
|
48 |
{% if pages|length > 1 %} |
|
49 |
<div class="pagination"> |
|
50 |
<ul> |
|
51 |
{% if prev %} |
|
52 |
<li class="prev"><a href="?page={{ prev }}{% if filter %}&filter={{ filter }}{% endif %}">← Previous</a></li> |
|
53 |
{% else %} |
|
54 |
<li class="prev disabled"><a href="#">← Previous</a></li> |
|
55 |
{% endif %} |
|
56 |
|
|
57 |
{% for p in pages %} |
|
58 |
<li{% if page == p %} class="active"{% endif %}><a href="?page={{ p }}{% if filter %}&filter={{ filter }}{% endif %}">{{ p }}</a></li> |
|
59 |
{% endfor %} |
|
60 |
|
|
61 |
{% if next %} |
|
62 |
<li class="next"><a href="?page={{ next }}{% if filter %}&filter={{ filter }}{% endif %}">→ Next</a></li> |
|
63 |
{% else %} |
|
64 |
<li class="next disabled"><a href="#">→ Next</a></li> |
|
65 |
{% endif %} |
|
66 |
</ul> |
|
67 |
</div> |
|
68 |
{% endif %} |
|
69 |
|
|
70 |
<form action="{% url pithos.im.views.invitations_export %}" method="post"> |
|
71 |
<button type="submit" class="btn primary">Export</button> |
|
72 |
</form> |
|
73 |
|
|
74 |
<br /><br /> |
|
75 |
{% endblock body %} |
b/pithos/im/urls.py | ||
---|---|---|
45 | 45 |
(r'^admin/users/(\d+)/?$', 'users_info'), |
46 | 46 |
(r'^admin/users/create$', 'users_create'), |
47 | 47 |
(r'^admin/users/(\d+)/modify/?$', 'users_modify'), |
48 |
(r'^admin/users/(\d+)/delete/?$', 'users_delete') |
|
48 |
(r'^admin/users/(\d+)/delete/?$', 'users_delete'), |
|
49 |
|
|
50 |
(r'^admin/invitations/?$', 'invitations_list'), |
|
51 |
(r'^admin/invitations/export/?$', 'invitations_export'), |
|
49 | 52 |
) |
50 | 53 |
|
51 | 54 |
urlpatterns += patterns('pithos.im.target', |
b/pithos/im/views.py | ||
---|---|---|
34 | 34 |
import json |
35 | 35 |
import logging |
36 | 36 |
import socket |
37 |
import csv |
|
37 | 38 |
|
38 | 39 |
from datetime import datetime |
39 | 40 |
from functools import wraps |
... | ... | |
138 | 139 |
page=page, |
139 | 140 |
prev=prev, |
140 | 141 |
next=next) |
141 |
|
|
142 |
@requires_admin |
|
143 |
def users_create(request): |
|
144 |
if request.method == 'GET': |
|
145 |
return render_response('users_create.html') |
|
146 |
if request.method == 'POST': |
|
147 |
user = User() |
|
148 |
user.uniq = request.POST.get('uniq') |
|
149 |
user.realname = request.POST.get('realname') |
|
150 |
user.is_admin = True if request.POST.get('admin') else False |
|
151 |
user.affiliation = request.POST.get('affiliation') |
|
152 |
user.quota = int(request.POST.get('quota') or 0) * (1024 ** 3) # In GiB |
|
153 |
user.renew_token() |
|
154 |
user.save() |
|
155 |
return redirect(users_info, user.id) |
|
156 | 142 |
|
157 | 143 |
@requires_admin |
158 | 144 |
def users_info(request, user_id): |
... | ... | |
366 | 352 |
'status': status, |
367 | 353 |
'message': message}) |
368 | 354 |
return HttpResponse(html) |
355 |
|
|
356 |
@requires_admin |
|
357 |
def invitations_list(request): |
|
358 |
invitations = Invitation.objects.order_by('id') |
|
359 |
|
|
360 |
filter = request.GET.get('filter', '') |
|
361 |
if filter: |
|
362 |
if filter.startswith('-'): |
|
363 |
invitations = invitations.exclude(uniq__icontains=filter[1:]) |
|
364 |
else: |
|
365 |
invitations = invitations.filter(uniq__icontains=filter) |
|
366 |
|
|
367 |
try: |
|
368 |
page = int(request.GET.get('page', 1)) |
|
369 |
except ValueError: |
|
370 |
page = 1 |
|
371 |
offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT |
|
372 |
limit = offset + settings.ADMIN_PAGE_LIMIT |
|
373 |
|
|
374 |
npages = int(ceil(1.0 * invitations.count() / settings.ADMIN_PAGE_LIMIT)) |
|
375 |
prev = page - 1 if page > 1 else None |
|
376 |
next = page + 1 if page < npages else None |
|
377 |
return render_response('invitations_list.html', |
|
378 |
invitations=invitations[offset:limit], |
|
379 |
filter=filter, |
|
380 |
pages=range(1, npages + 1), |
|
381 |
page=page, |
|
382 |
prev=prev, |
|
383 |
next=next) |
|
384 |
|
|
385 |
@requires_admin |
|
386 |
def invitations_export(request): |
|
387 |
# Create the HttpResponse object with the appropriate CSV header. |
|
388 |
response = HttpResponse(mimetype='text/csv') |
|
389 |
response['Content-Disposition'] = 'attachment; filename=invitations.csv' |
|
390 |
|
|
391 |
writer = csv.writer(response) |
|
392 |
writer.writerow(['ID', |
|
393 |
'Uniq', |
|
394 |
'Real Name', |
|
395 |
'Code', |
|
396 |
'Inviter Uniq', |
|
397 |
'Inviter Real Name', |
|
398 |
'Is_accepted', |
|
399 |
'Created', |
|
400 |
'Accepted',]) |
|
401 |
invitations = Invitation.objects.order_by('id') |
|
402 |
for inv in invitations: |
|
403 |
writer.writerow([inv.id, |
|
404 |
inv.uniq, |
|
405 |
inv.realname.encode("utf-8"), |
|
406 |
inv.code, |
|
407 |
inv.inviter.uniq, |
|
408 |
inv.inviter.realname.encode("utf-8"), |
|
409 |
inv.is_accepted, |
|
410 |
inv.created, |
|
411 |
inv.accepted, |
|
412 |
]) |
|
413 |
|
|
414 |
return response |
|
415 |
|
|
416 |
@requires_admin |
|
417 |
def users_create(request): |
|
418 |
if request.method == 'GET': |
|
419 |
return render_response('users_create.html') |
|
420 |
if request.method == 'POST': |
|
421 |
user = User() |
|
422 |
user.uniq = request.POST.get('uniq') |
|
423 |
user.realname = request.POST.get('realname') |
|
424 |
user.is_admin = True if request.POST.get('admin') else False |
|
425 |
user.affiliation = request.POST.get('affiliation') |
|
426 |
user.quota = int(request.POST.get('quota') or 0) * (1024 ** 3) # In GiB |
|
427 |
user.renew_token() |
|
428 |
user.save() |
|
429 |
return redirect(users_info, user.id) |
Also available in: Unified diff