Skip to content

Commit

Permalink
Add the ability to view users in a group
Browse files Browse the repository at this point in the history
* adds users view to group view (users filtered by that group)
* adds the ability to go to the users list for the group currently being edited (via header link)
* fix issue where the link to add a new user (when no users found) was broken
* resolves #5801
  • Loading branch information
karranb authored and lb- committed Apr 26, 2020
1 parent 2055da6 commit 7565248
Show file tree
Hide file tree
Showing 18 changed files with 121 additions and 24 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.txt
Expand Up @@ -7,6 +7,8 @@ Changelog
* Removed support for Python 3.5
* Reorganised Dockerfile in project template to follow best practices (Tomasz Knapik, Jannik Wempe)
* Added filtering to locked pages report (Karl Hobley)
* Adds ability to view a group's users via standalone admin URL and a link to this on the group edit view (Karran Besen)
* Fix: Ensure link to add a new user works when no users are visible in the users list (LB (Ben Johnston))


2.9 (xx.xx.xxxx) - IN DEVELOPMENT
Expand Down
2 changes: 1 addition & 1 deletion client/scss/components/_header.scss
Expand Up @@ -146,7 +146,7 @@ header {
@include column(3);
}

.col3.addbutton {
.col3.actionbutton {
width: auto;
}

Expand Down
3 changes: 2 additions & 1 deletion docs/releases/2.10.rst
Expand Up @@ -16,12 +16,13 @@ Other features

* Reorganised Dockerfile in project template to follow best practices (Tomasz Knapik, Jannik Wempe)
* Added filtering to locked pages report (Karl Hobley)
* Adds ability to view a group's users via standalone admin URL and a link to this on the group edit view (Karran Besen)


Bug fixes
~~~~~~~~~

* ...
* Ensure link to add a new user works when no users are visible in the users list (LB (Ben Johnston))


Upgrade considerations
Expand Down
3 changes: 2 additions & 1 deletion wagtail/admin/templates/wagtailadmin/generic/index.html
Expand Up @@ -3,7 +3,8 @@
{% block titletag %}{{ view.page_title }}{% endblock %}
{% block content %}
{% if can_add %}
{% include "wagtailadmin/shared/header.html" with title=view.page_title add_link=view.add_url_name add_text=view.add_item_label icon=view.header_icon %}
{% url view.add_url_name as add_link %}
{% include "wagtailadmin/shared/header.html" with title=view.page_title action_url=add_link action_text=view.add_item_label icon=view.header_icon %}
{% else %}
{% include "wagtailadmin/shared/header.html" with title=view.page_title icon=view.header_icon %}
{% endif %}
Expand Down
12 changes: 7 additions & 5 deletions wagtail/admin/templates/wagtailadmin/shared/header.html
Expand Up @@ -14,8 +14,10 @@
tabbed - if true, add the classname 'tab-merged'
merged - if true, add the classname 'merged'

add_link - if present, display an 'add' button. This is a URL route name (taking no parameters) to be used as the link URL for the button
add_text - text for the 'add' button
action_url - if present, display an 'action' button. This is the URL to be used as the link URL for the button
action_text - text for the 'action' button
action_icon - icon for the 'action' button, default is 'icon-plus'

{% endcomment %}
<header class="{% if merged %}merged{% endif %} {% if tabbed %}tab-merged{% endif %} {% if search_form %}hasform{% endif %}">
{% block breadcrumb %}{% endblock %}
Expand All @@ -37,9 +39,9 @@ <h1 class="icon icon-{{ icon }}">
{% endif %}
</div>
<div class="right">
{% if add_link %}
<div class="addbutton">
<a href="{% url add_link %}" class="button bicolor icon icon-plus">{{ add_text }}</a>
{% if action_url %}
<div class="actionbutton">
<a href="{{ action_url }}" class="button bicolor icon {{ action_icon|default:'icon-plus' }}">{{ action_text }}</a>
</div>
{% endif %}
</div>
Expand Down
4 changes: 2 additions & 2 deletions wagtail/contrib/modeladmin/templates/modeladmin/index.html
Expand Up @@ -26,9 +26,9 @@
{% block header_extra %}
<div class="right">
{% if user_can_create %}
<span class="addbutton">
<div class="actionbutton">
{% include 'modeladmin/includes/button.html' with button=view.button_helper.add_button %}
</span>
</div>
{% endif %}
{% if view.list_export %}
<div class="dropdown dropdown-button match-width col">
Expand Down
Expand Up @@ -17,7 +17,8 @@
{% trans "Redirects" as redirects_str %}
{% trans "Add redirect" as add_str %}
{% if user_can_add %}
{% include "wagtailadmin/shared/header.html" with title=redirects_str icon="redirect" add_link="wagtailredirects:add" add_text=add_str search_url="wagtailredirects:index" %}
{% url "wagtailredirects:add" as add_link %}
{% include "wagtailadmin/shared/header.html" with title=redirects_str icon="redirect" action_url=add_link action_text=add_str search_url="wagtailredirects:index" %}
{% else %}
{% include "wagtailadmin/shared/header.html" with title=redirects_str icon="redirect" search_url="wagtailredirects:index" %}
{% endif %}
Expand Down
Expand Up @@ -16,7 +16,9 @@
{% block content %}
{% trans "Promoted search results" as sp_title_str %}
{% trans "Add new promoted result" as sp_text_str %}
{% include "wagtailadmin/shared/header.html" with title=sp_title_str add_link="wagtailsearchpromotions:add" icon="pick" add_text=sp_text_str search_url="wagtailsearchpromotions:index" %}

{% url "wagtailsearchpromotions:add" as add_link %}
{% include "wagtailadmin/shared/header.html" with title=sp_title_str action_url=add_link icon="pick" action_text=sp_text_str search_url="wagtailsearchpromotions:index" %}

<div class="nice-padding">
<div id="editorspicks-results" class="redirects">
Expand Down
Expand Up @@ -663,7 +663,8 @@ <h2>Header</h2>

{% include "wagtailadmin/shared/header.html" with title=title_trans %}

{% include "wagtailadmin/shared/header.html" with title=title_trans add_link="wagtailstyleguide" icon="image" add_text="button" search_url="wagtailimages:index" %}
{% url "wagtailstyleguide" as add_link %}
{% include "wagtailadmin/shared/header.html" with title=title_trans action_url=add_link icon="image" action_text="button" search_url="wagtailimages:index" %}
</section>

<section id="forms">
Expand Down
3 changes: 2 additions & 1 deletion wagtail/documents/templates/wagtaildocs/documents/index.html
Expand Up @@ -23,7 +23,8 @@

{% if user_can_add %}
{% trans "Add a document" as add_doc_str %}
{% include "wagtailadmin/shared/header.html" with title=doc_str add_link="wagtaildocs:add_multiple" icon="doc-full-inverse" add_text=add_doc_str search_url="wagtaildocs:index" %}
{% url "wagtaildocs:add_multiple" as add_link %}
{% include "wagtailadmin/shared/header.html" with title=doc_str action_url=add_link icon="doc-full-inverse" action_text=add_doc_str search_url="wagtaildocs:index" %}
{% else %}
{% include "wagtailadmin/shared/header.html" with title=doc_str icon="doc-full-inverse" search_url="wagtaildocs:index" %}
{% endif %}
Expand Down
3 changes: 2 additions & 1 deletion wagtail/images/templates/wagtailimages/images/index.html
Expand Up @@ -26,7 +26,8 @@

{% if user_can_add %}
{% trans "Add an image" as add_img_str %}
{% include "wagtailadmin/shared/header.html" with title=im_str add_link="wagtailimages:add_multiple" icon="image" add_text=add_img_str search_url="wagtailimages:index" %}
{% url "wagtailimages:add_multiple" as add_link %}
{% include "wagtailadmin/shared/header.html" with title=im_str action_url=add_link icon="image" action_text=add_img_str search_url="wagtailimages:index" %}
{% else %}
{% include "wagtailadmin/shared/header.html" with title=im_str icon="image" search_url="wagtailimages:index" %}
{% endif %}
Expand Down
4 changes: 3 additions & 1 deletion wagtail/users/templates/wagtailusers/groups/edit.html
Expand Up @@ -13,7 +13,9 @@
{% block content %}

{% trans "Editing" as editing_str %}
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=group.name icon="group" %}
{% trans "View users of this group" as users_str %}
{% url 'wagtailusers_groups:users' group.id as group_users_url %}
{% include "wagtailadmin/shared/header.html" with title=editing_str action_icon="icon-user" action_url=group_users_url action_text=users_str subtitle=group.name icon="group" %}

<div class="nice-padding">
<form action="{% url 'wagtailusers_groups:edit' group.id %}" method="POST" novalidate>
Expand Down
3 changes: 2 additions & 1 deletion wagtail/users/templates/wagtailusers/groups/index.html
Expand Up @@ -15,7 +15,8 @@
{% block content %}
{% trans "groups" as groups_str %}
{% trans "Add a group" as add_a_group_str %}
{% include "wagtailadmin/shared/header.html" with title=groups_str add_link="wagtailusers_groups:add" add_text=add_a_group_str icon="group" search_url="wagtailusers_groups:index" %}
{% url "wagtailusers_groups:add" as add_link %}
{% include "wagtailadmin/shared/header.html" with title=groups_str action_url=add_link action_text=add_a_group_str icon="group" search_url="wagtailusers_groups:index" %}

<div class="nice-padding">
<div id="group-results" class="groups">
Expand Down
8 changes: 7 additions & 1 deletion wagtail/users/templates/wagtailusers/users/index.html
Expand Up @@ -5,7 +5,11 @@
{{ block.super }}
<script>
window.headerSearch = {
{% if group %}
url: "{% url 'wagtailusers_groups:users' group.id %}",
{% else %}
url: "{% url 'wagtailusers_users:index' %}",
{% endif %}
termInput: "#id_q",
targetOutput: "#user-results"
}
Expand All @@ -15,7 +19,9 @@
{% block content %}
{% trans "Users" as users_str %}
{% trans "Add a user" as add_a_user_str %}
{% include "wagtailadmin/shared/header.html" with title=users_str add_link="wagtailusers_users:add" add_text=add_a_user_str icon="user" search_url="wagtailusers_users:index" %}

{% url "wagtailusers_users:add" as add_link %}
{% include "wagtailadmin/shared/header.html" with subtitle=group.name title=users_str action_url=add_link action_text=add_a_user_str icon="user" search_url="wagtailusers_users:index" %}

<div class="nice-padding">
<div id="user-results" class="users">
Expand Down
10 changes: 8 additions & 2 deletions wagtail/users/templates/wagtailusers/users/results.html
Expand Up @@ -21,7 +21,13 @@ <h2 role="alert">{% blocktrans %}Sorry, no users match "<em>{{ query_string }}</

{% search_other %}
{% else %}
{% url 'wagtailusers_create' as wagtailusers_create_url %}
<p>{% blocktrans %}There are no users configured. Why not <a href="{{ wagtailusers_create_url }}">add some</a>?{% endblocktrans %}</p>
{% url 'wagtailusers_users:add' as wagtailusers_add_url %}
{% if group %}
{% with group.name as group_name %}
<p>{% blocktrans %}The {{ group_name }} group has no users configured. Why not <a href="{{ wagtailusers_add_url }}">add some</a>?{% endblocktrans %}</p>
{% endwith %}
{% else %}
<p>{% blocktrans %}There are no users configured. Why not <a href="{{ wagtailusers_add_url }}">add some</a>?{% endblocktrans %}</p>
{% endif %}
{% endif %}
{% endif %}
51 changes: 51 additions & 0 deletions wagtail/users/tests.py
Expand Up @@ -70,6 +70,57 @@ def test_get_user_edit_form_with_invalid_form(self):
self.assertRaises(ImproperlyConfigured, get_user_edit_form)


class TestGroupUsersView(TestCase, WagtailTestUtils):
def setUp(self):
# create a user that should be visible in the listing
self.test_user = get_user_model().objects.create_user(
username='testuser',
email='testuser@email.com',
password='password',
first_name='First Name',
last_name='Last Name'
)
self.test_group = Group.objects.create(name='Test Group')
self.test_user.groups.add(self.test_group)
self.login()

def get(self, params={}, group_id=None):
return self.client.get(reverse('wagtailusers_groups:users', args=(group_id or self.test_group.pk, )), params)

def test_simple(self):
response = self.get()
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailusers/users/index.html')
self.assertContains(response, 'testuser')

def test_inexisting_group(self):
response = self.get(group_id=9999)
self.assertEqual(response.status_code, 404)

def test_search(self):
response = self.get({'q': "Hello"})
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context['query_string'], "Hello")

def test_search_query_one_field(self):
response = self.get({'q': "first name"})
self.assertEqual(response.status_code, 200)
results = response.context['users'].object_list
self.assertIn(self.test_user, results)

def test_search_query_multiple_fields(self):
response = self.get({'q': "first name last name"})
self.assertEqual(response.status_code, 200)
results = response.context['users'].object_list
self.assertIn(self.test_user, results)

def test_pagination(self):
pages = ['0', '1', '-1', '9999', 'Not a page']
for page in pages:
response = self.get({'p': page})
self.assertEqual(response.status_code, 200)


class TestUserIndexView(TestCase, WagtailTestUtils):
def setUp(self):
# create a user that should be visible in the listing
Expand Down
13 changes: 12 additions & 1 deletion wagtail/users/views/groups.py
@@ -1,11 +1,12 @@
from django.conf.urls import url
from django.contrib.auth.models import Group
from django.utils.translation import gettext as _

from wagtail.admin.views import generic, mixins
from wagtail.admin.viewsets.model import ModelViewSet
from wagtail.core import hooks
from wagtail.users.forms import GroupForm, GroupPagePermissionFormSet

from wagtail.users.views.users import index
_permission_panel_classes = None


Expand Down Expand Up @@ -155,5 +156,15 @@ class GroupViewSet(ModelViewSet):
edit_view_class = EditView
delete_view_class = DeleteView


@property
def users_view(self):
return index

def get_form_class(self, for_update=False):
return GroupForm

def get_urlpatterns(self):
return super().get_urlpatterns() + [
url(r'^(\d+)/users/$', self.users_view, name='users'),
]
14 changes: 11 additions & 3 deletions wagtail/users/views/users.py
@@ -1,5 +1,6 @@
from django.conf import settings
from django.contrib.auth import get_user_model, update_session_auth_hash
from django.contrib.auth.models import Group
from django.core.paginator import Paginator
from django.db.models import Q
from django.shortcuts import get_object_or_404, redirect
Expand Down Expand Up @@ -45,10 +46,16 @@ def get_user_edit_form():

@any_permission_required(add_user_perm, change_user_perm, delete_user_perm)
@vary_on_headers('X-Requested-With')
def index(request):
def index(request, *args):
q = None
is_searching = False

group = None
group_filter = Q()
if args:
group = get_object_or_404(Group, id=args[0])
group_filter = Q(groups=group) if args else Q()

model_fields = [f.name for f in User._meta.get_fields()]

if 'q' in request.GET:
Expand All @@ -71,12 +78,12 @@ def index(request):
if 'email' in model_fields:
conditions |= Q(email__icontains=term)

users = User.objects.filter(conditions)
users = User.objects.filter(group_filter & conditions)
else:
form = SearchForm(placeholder=_("Search users"))

if not is_searching:
users = User.objects.all()
users = User.objects.filter(group_filter)

if 'last_name' in model_fields and 'first_name' in model_fields:
users = users.order_by('last_name', 'first_name')
Expand All @@ -101,6 +108,7 @@ def index(request):
})
else:
return TemplateResponse(request, "wagtailusers/users/index.html", {
'group': group,
'search_form': form,
'users': users,
'is_searching': is_searching,
Expand Down

0 comments on commit 7565248

Please sign in to comment.