--- /dev/null
+{% extends "base.html" %}
+
+{% load formatters %}
+
+{% block body %}
+
+<div class="row">
+ <div class="offset10 span3">
+ <form method="get">
+ <div class="input">
+ <input class="span3" name="filter" type="search" placeholder="search" value="{{ filter }}">
+ </div>
+ </form>
+ </div>
+</div>
+
+<table class="zebra-striped id-sorted">
+ <thead>
+ <tr>
+ <th>ID</th>
+ <th>Uniq</th>
+ <th>Real Name</th>
+ <th>Code</th>
+ <th>Inviter Uniq</th>
+ <th>Inviter Real Name</th>
+ <th>Is_accepted</th>
+ <th>Created</th>
+ <th>Accepted</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for inv in invitations %}
+ <tr>
+ <td>{{ inv.id }}</td>
+ <td>{{ inv.uniq }}</td>
+ <td>{{ inv.realname }}</td>
+ <td>{{ inv.code }}</td>
+ <td>{{ inv.inviter.uniq }}</td>
+ <td>{{ inv.inviter.realname }}</td>
+ <td>{{ inv.is_accepted }}</td>
+ <td>{{ inv.created }}</td>
+ <td>{{ inv.accepted }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+
+{% if pages|length > 1 %}
+<div class="pagination">
+ <ul>
+ {% if prev %}
+ <li class="prev"><a href="?page={{ prev }}{% if filter %}&filter={{ filter }}{% endif %}">← Previous</a></li>
+ {% else %}
+ <li class="prev disabled"><a href="#">← Previous</a></li>
+ {% endif %}
+
+ {% for p in pages %}
+ <li{% if page == p %} class="active"{% endif %}><a href="?page={{ p }}{% if filter %}&filter={{ filter }}{% endif %}">{{ p }}</a></li>
+ {% endfor %}
+
+ {% if next %}
+ <li class="next"><a href="?page={{ next }}{% if filter %}&filter={{ filter }}{% endif %}">→ Next</a></li>
+ {% else %}
+ <li class="next disabled"><a href="#">→ Next</a></li>
+ {% endif %}
+ </ul>
+</div>
+{% endif %}
+
+<form action="{% url pithos.im.views.invitations_export %}" method="post">
+<button type="submit" class="btn primary">Export</button>
+</form>
+
+<br /><br />
+{% endblock body %}
(r'^admin/users/(\d+)/?$', 'users_info'),
(r'^admin/users/create$', 'users_create'),
(r'^admin/users/(\d+)/modify/?$', 'users_modify'),
- (r'^admin/users/(\d+)/delete/?$', 'users_delete')
+ (r'^admin/users/(\d+)/delete/?$', 'users_delete'),
+
+ (r'^admin/invitations/?$', 'invitations_list'),
+ (r'^admin/invitations/export/?$', 'invitations_export'),
)
urlpatterns += patterns('pithos.im.target',
import json
import logging
import socket
+import csv
from datetime import datetime
from functools import wraps
page=page,
prev=prev,
next=next)
-
-@requires_admin
-def users_create(request):
- if request.method == 'GET':
- return render_response('users_create.html')
- if request.method == 'POST':
- user = User()
- user.uniq = request.POST.get('uniq')
- user.realname = request.POST.get('realname')
- user.is_admin = True if request.POST.get('admin') else False
- user.affiliation = request.POST.get('affiliation')
- user.quota = int(request.POST.get('quota') or 0) * (1024 ** 3) # In GiB
- user.renew_token()
- user.save()
- return redirect(users_info, user.id)
@requires_admin
def users_info(request, user_id):
'status': status,
'message': message})
return HttpResponse(html)
+
+@requires_admin
+def invitations_list(request):
+ invitations = Invitation.objects.order_by('id')
+
+ filter = request.GET.get('filter', '')
+ if filter:
+ if filter.startswith('-'):
+ invitations = invitations.exclude(uniq__icontains=filter[1:])
+ else:
+ invitations = invitations.filter(uniq__icontains=filter)
+
+ try:
+ page = int(request.GET.get('page', 1))
+ except ValueError:
+ page = 1
+ offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT
+ limit = offset + settings.ADMIN_PAGE_LIMIT
+
+ npages = int(ceil(1.0 * invitations.count() / settings.ADMIN_PAGE_LIMIT))
+ prev = page - 1 if page > 1 else None
+ next = page + 1 if page < npages else None
+ return render_response('invitations_list.html',
+ invitations=invitations[offset:limit],
+ filter=filter,
+ pages=range(1, npages + 1),
+ page=page,
+ prev=prev,
+ next=next)
+
+@requires_admin
+def invitations_export(request):
+ # Create the HttpResponse object with the appropriate CSV header.
+ response = HttpResponse(mimetype='text/csv')
+ response['Content-Disposition'] = 'attachment; filename=invitations.csv'
+
+ writer = csv.writer(response)
+ writer.writerow(['ID',
+ 'Uniq',
+ 'Real Name',
+ 'Code',
+ 'Inviter Uniq',
+ 'Inviter Real Name',
+ 'Is_accepted',
+ 'Created',
+ 'Accepted',])
+ invitations = Invitation.objects.order_by('id')
+ for inv in invitations:
+ writer.writerow([inv.id,
+ inv.uniq,
+ inv.realname.encode("utf-8"),
+ inv.code,
+ inv.inviter.uniq,
+ inv.inviter.realname.encode("utf-8"),
+ inv.is_accepted,
+ inv.created,
+ inv.accepted,
+ ])
+
+ return response
+
+@requires_admin
+def users_create(request):
+ if request.method == 'GET':
+ return render_response('users_create.html')
+ if request.method == 'POST':
+ user = User()
+ user.uniq = request.POST.get('uniq')
+ user.realname = request.POST.get('realname')
+ user.is_admin = True if request.POST.get('admin') else False
+ user.affiliation = request.POST.get('affiliation')
+ user.quota = int(request.POST.get('quota') or 0) * (1024 ** 3) # In GiB
+ user.renew_token()
+ user.save()
+ return redirect(users_info, user.id)