Commit e9ee55cc by Bach Dániel

dashboard: add user list view

parent 30d8fe06
...@@ -1494,3 +1494,10 @@ class TemplateListSearchForm(forms.Form): ...@@ -1494,3 +1494,10 @@ class TemplateListSearchForm(forms.Form):
data = self.data.copy() data = self.data.copy()
data['stype'] = "owned" data['stype'] = "owned"
self.data = data self.data = data
class UserListSearchForm(forms.Form):
s = forms.CharField(widget=forms.TextInput(attrs={
'class': "form-control input-tags",
'placeholder': _("Search...")
}))
...@@ -123,26 +123,24 @@ class GroupListTable(Table): ...@@ -123,26 +123,24 @@ class GroupListTable(Table):
class UserListTable(Table): class UserListTable(Table):
pk = TemplateColumn( username = LinkColumn(
template_name='dashboard/vm-list/column-id.html', 'dashboard.views.profile',
verbose_name="ID", args=[A('username')],
attrs={'th': {'class': 'vm-list-table-thin'}},
) )
profile__org_id = LinkColumn(
username = TemplateColumn( 'dashboard.views.profile',
template_name="dashboard/group-list/column-username.html" accessor='profile.org_id',
args=[A('username')],
verbose_name=_('Organization ID')
) )
is_superuser = BooleanColumn()
is_active = BooleanColumn()
class Meta: class Meta:
model = User model = User
attrs = {'class': ('table table-bordered table-striped table-hover ' attrs = {'class': ('table table-bordered table-striped table-hover')}
'vm-list-table')} fields = ('username', 'last_name', 'first_name', 'profile__org_id',
fields = ('pk', 'username', ) 'email', 'is_active', 'is_superuser')
class UserListTablex(Table):
class Meta:
model = User
class TemplateListTable(Table): class TemplateListTable(Table):
......
{% load i18n %}
<div class="panel panel-default">
<div class="panel-heading">
<div class="pull-right toolbar">
<span class="btn btn-default btn-xs infobtn" data-container="body" title="{% trans "List of CIRCLE users." %}"><i class="fa fa-info-circle"></i></span>
</div>
<h3 class="no-margin"><i class="fa fa-users"></i> {% trans "Users" %}</h3>
</div>
<div class="list-group" id="user-list-view">
<div id="dashboard-user-list">
{% for i in users %}
<a href="{% url "dashboard.views.profile" username=i.username %}" class="list-group-item real-link
{% if forloop.last and users|length < 5 %} list-group-item-last{% endif %}">
<i class="fa fa-user"></i> {% firstof i.get_full_name|safe i.username|safe %}
</a>
{% endfor %}
</div>
<div class="list-group-item list-group-footer text-right">
<div class="row">
<div class="col-xs-6">
<form action="{% url "dashboard.views.user-list" %}" method="GET" id="dashboard-user-search-form">
<div class="input-group input-group-sm">
<input id="dashboard-group-search-input" name="s" type="text" class="form-control" placeholder="{% trans "Search..." %}" />
<div class="input-group-btn">
<button type="submit" class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</form>
</div>
<div class="col-xs-6 text-right">
<a class="btn btn-primary btn-xs" href="{% url "dashboard.views.user-list" %}">
<i class="fa fa-chevron-circle-right"></i>
{% if more_users > 0 %}
{% blocktrans count more=more_users %}
<strong>{{ more }}</strong> more
{% plural %}
<strong>{{ more }}</strong> more
{% endblocktrans %}
{% else %}
{% trans "list" %}
{% endif %}
</a>
<a class="btn btn-success btn-xs user-create" href="{% url "dashboard.views.group-create" %}"><i class="fa fa-plus-circle"></i> {% trans "new" %} </a>
</div>
</div>
</div>
</div>
</div>
...@@ -48,6 +48,12 @@ ...@@ -48,6 +48,12 @@
{% include "dashboard/index-nodes.html" %} {% include "dashboard/index-nodes.html" %}
</div> </div>
{% endif %} {% endif %}
{% if perms.auth.change_user %}
<div class="col-lg-4 col-sm-6">
{% include "dashboard/index-users.html" %}
</div>
{% endif %}
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load i18n %}
{% load render_table from django_tables2 %}
{% block title-page %}{% trans "Users" %}{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<a href="{% url "dashboard.views.template-choose" %}" class="pull-right btn btn-success btn-xs template-choose">
<i class="fa fa-plus"></i> {% trans "new user" %}
</a>
<h3 class="no-margin"><i class="fa fa-user"></i> {% trans "Users" %}</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-offset-8 col-md-4" id="template-list-search">
<form action="" method="GET">
<div class="input-group">
{{ search_form.s }}
<div class="input-group-btn">
{{ search_form.stype }}
<button type="submit" class="btn btn-primary input-tags">
<i class="fa fa-search"></i>
</button>
</div>
</div><!-- .input-group -->
</form>
</div><!-- .col-md-4 #template-list-search -->
</div>
</div>
<div class="panel-body">
<div class="table-responsive">
{% render_table table %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
...@@ -52,6 +52,7 @@ from .views import ( ...@@ -52,6 +52,7 @@ from .views import (
TransferTemplateOwnershipView, TransferTemplateOwnershipConfirmView, TransferTemplateOwnershipView, TransferTemplateOwnershipConfirmView,
OpenSearchDescriptionView, OpenSearchDescriptionView,
NodeActivityView, NodeActivityView,
UserList,
) )
from .views.vm import vm_ops, vm_mass_ops from .views.vm import vm_ops, vm_mass_ops
from .views.node import node_ops from .views.node import node_ops
...@@ -61,6 +62,8 @@ autocomplete_light.autodiscover() ...@@ -61,6 +62,8 @@ autocomplete_light.autodiscover()
urlpatterns = patterns( urlpatterns = patterns(
'', '',
url(r'^$', IndexView.as_view(), name="dashboard.index"), url(r'^$', IndexView.as_view(), name="dashboard.index"),
url(r"^profile/list/$", UserList.as_view(),
name="dashboard.views.user-list"),
url(r'^lease/(?P<pk>\d+)/$', LeaseDetail.as_view(), url(r'^lease/(?P<pk>\d+)/$', LeaseDetail.as_view(),
name="dashboard.views.lease-detail"), name="dashboard.views.lease-detail"),
url(r'^lease/create/$', LeaseCreate.as_view(), url(r'^lease/create/$', LeaseCreate.as_view(),
......
...@@ -21,7 +21,7 @@ import logging ...@@ -21,7 +21,7 @@ import logging
from django.core.cache import get_cache from django.core.cache import get_cache
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import Group from django.contrib.auth.models import Group, User
from django.views.generic import TemplateView from django.views.generic import TemplateView
from braces.views import LoginRequiredMixin from braces.views import LoginRequiredMixin
...@@ -86,6 +86,14 @@ class IndexView(LoginRequiredMixin, TemplateView): ...@@ -86,6 +86,14 @@ class IndexView(LoginRequiredMixin, TemplateView):
'more_groups': groups.count() - len(groups[:5]), 'more_groups': groups.count() - len(groups[:5]),
}) })
# users
if user.has_module_perms('auth.change_user'):
users = User.objects.all()
context.update({
'users': users[:5],
'more_users': users.count() - len(users[:5]),
})
# template # template
if user.has_perm('vm.create_template'): if user.has_perm('vm.create_template'):
context['templates'] = InstanceTemplate.get_objects_with_level( context['templates'] = InstanceTemplate.get_objects_with_level(
......
...@@ -31,6 +31,7 @@ from django.core.exceptions import ( ...@@ -31,6 +31,7 @@ from django.core.exceptions import (
) )
from django.core.urlresolvers import reverse, reverse_lazy from django.core.urlresolvers import reverse, reverse_lazy
from django.core.paginator import Paginator, InvalidPage from django.core.paginator import Paginator, InvalidPage
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect, Http404 from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import redirect, get_object_or_404 from django.shortcuts import redirect, get_object_or_404
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
...@@ -42,14 +43,19 @@ from django_sshkey.models import UserKey ...@@ -42,14 +43,19 @@ from django_sshkey.models import UserKey
from braces.views import LoginRequiredMixin, PermissionRequiredMixin from braces.views import LoginRequiredMixin, PermissionRequiredMixin
from django_tables2 import SingleTableView
from vm.models import Instance, InstanceTemplate from vm.models import Instance, InstanceTemplate
from ..forms import ( from ..forms import (
CircleAuthenticationForm, MyProfileForm, UserCreationForm, UnsubscribeForm, CircleAuthenticationForm, MyProfileForm, UserCreationForm, UnsubscribeForm,
UserKeyForm, CirclePasswordChangeForm, ConnectCommandForm, UserKeyForm, CirclePasswordChangeForm, ConnectCommandForm,
UserListSearchForm,
) )
from ..models import Profile, GroupProfile, ConnectCommand, create_profile from ..models import Profile, GroupProfile, ConnectCommand, create_profile
from ..tables import UserKeyListTable, ConnectCommandListTable from ..tables import (
UserKeyListTable, ConnectCommandListTable, UserListTable,
)
from .util import saml_available, DeleteViewBase from .util import saml_available, DeleteViewBase
...@@ -480,3 +486,46 @@ class ConnectCommandCreate(LoginRequiredMixin, SuccessMessageMixin, ...@@ -480,3 +486,46 @@ class ConnectCommandCreate(LoginRequiredMixin, SuccessMessageMixin,
kwargs = super(ConnectCommandCreate, self).get_form_kwargs() kwargs = super(ConnectCommandCreate, self).get_form_kwargs()
kwargs['user'] = self.request.user kwargs['user'] = self.request.user
return kwargs return kwargs
class UserList(LoginRequiredMixin, PermissionRequiredMixin, SingleTableView):
template_name = "dashboard/user-list.html"
permission_required = "auth.change_user"
model = User
table_class = UserListTable
table_pagination = True
def get_context_data(self, *args, **kwargs):
context = super(UserList, self).get_context_data(*args, **kwargs)
context['search_form'] = self.search_form
return context
def get(self, *args, **kwargs):
self.search_form = UserListSearchForm(self.request.GET)
self.search_form.full_clean()
if self.request.is_ajax():
users = [
{'url': reverse("dashboard.views.profile", args=[i.username]),
'name': i.get_full_name() or i.username}
for i in self.get_queryset()]
return HttpResponse(
json.dumps(users), content_type="application/json")
else:
return super(UserList, self).get(*args, **kwargs)
def get_queryset(self):
logger.debug('UserList.get_queryset() called. User: %s',
unicode(self.request.user))
qs = User.objects.all()
q = self.search_form.cleaned_data.get('s')
if q:
filters = (Q(username__icontains=q) | Q(email__icontains=q)
| Q(profile__org_id__icontains=q))
for w in q.split()[:3]:
filters |= (
Q(first_name__icontains=w) | Q(last_name__icontains=w))
qs = qs.filter(filters)
return qs.select_related("profile")
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 sign in to comment