Skip to content

Commit 625e107

Browse files
committed
Update wagtail admin custom user and groups views and templates.
1 parent 13514b3 commit 625e107

15 files changed

Lines changed: 74 additions & 434 deletions

File tree

hypha/apply/apps.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from wagtail.users.apps import WagtailUsersAppConfig
2+
3+
4+
class CustomUsersAppConfig(WagtailUsersAppConfig):
5+
user_viewset = "hypha.apply.users.admin_views.CustomUserViewSet"
6+
group_viewset = "hypha.apply.users.admin_views.CustomGroupViewSet"

hypha/apply/users/admin_views.py

Lines changed: 48 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
import django_filters
22
from django.contrib.auth import get_user_model
33
from django.contrib.auth.models import Group
4-
from django.db.models import CharField, Q, Value
4+
from django.db.models import CharField, Value
55
from django.db.models.functions import Coalesce, Lower, NullIf
6+
from django.urls import reverse
7+
from django.utils.functional import cached_property
68
from django.utils.safestring import mark_safe
9+
from django.utils.translation import gettext
710
from rolepermissions import roles
811
from wagtail.admin.filters import WagtailFilterSet
12+
from wagtail.admin.utils import set_query_params
13+
from wagtail.admin.widgets.button import HeaderButton
914
from wagtail.compat import AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME
10-
from wagtail.users.views.groups import GroupViewSet
15+
from wagtail.users.views.groups import EditView as GroupEditView
16+
from wagtail.users.views.groups import GroupViewSet as WagtailGroupViewSet
1117
from wagtail.users.views.groups import IndexView as GroupIndexView
12-
from wagtail.users.views.users import Index as UserIndexView
13-
from wagtail.users.views.users import get_users_filter_query
18+
from wagtail.users.views.users import IndexView as UserIndexView
19+
from wagtail.users.views.users import UserViewSet as WagtailUserViewSet
20+
21+
from .forms import CustomUserCreationForm, CustomUserEditForm
1422

1523
User = get_user_model()
1624

@@ -55,12 +63,6 @@ def filter_by_status(self, queryset, name, value):
5563

5664

5765
class CustomUserIndexView(UserIndexView):
58-
"""
59-
Override wagtail's users index view to filter by full_name. This view
60-
also allows for the addition of custom fields to the list_export
61-
and list filtering.
62-
"""
63-
6466
list_export = [
6567
"email",
6668
"full_name",
@@ -72,69 +74,41 @@ class CustomUserIndexView(UserIndexView):
7274
"last_login",
7375
]
7476

75-
default_ordering = "name"
76-
list_filter = ("is_active",)
77-
78-
filterset_class = UserFilterSet
79-
80-
def get_context_data(self, *args, object_list=None, **kwargs):
81-
ctx = super().get_context_data(*args, object_list=object_list, **kwargs)
82-
ctx["filters"] = self.get_filterset_class()(
83-
self.request.GET, queryset=self.get_queryset(), request=self.request
84-
)
85-
return ctx
86-
87-
def get_queryset(self):
88-
"""
89-
Override the original queryset to filter by full_name, mostly copied from
90-
super().get_queryset() with the addition of the custom code
91-
"""
92-
model_fields = set(self.model_fields)
93-
if self.is_searching:
94-
conditions = get_users_filter_query(self.search_query, model_fields)
95-
96-
# == custom code
97-
for term in self.search_query.split():
98-
if "full_name" in model_fields:
99-
conditions |= Q(full_name__icontains=term)
100-
# == custom code end
101-
102-
users = User.objects.filter(self.group_filter & conditions)
103-
else:
104-
users = User.objects.filter(self.group_filter)
105-
106-
if self.locale:
107-
users = users.filter(locale=self.locale)
77+
def get_base_queryset(self):
78+
users = User._default_manager.all()
10879

10980
users = users.annotate(
11081
display_name=Coalesce(
11182
NullIf("full_name", Value("")), "email", output_field=CharField()
11283
),
11384
)
11485

115-
if "wagtail_userprofile" in model_fields:
86+
if "wagtail_userprofile" in self.model_fields:
11687
users = users.select_related("wagtail_userprofile")
11788

11889
# == custom code
119-
if "full_name" in model_fields:
90+
if "full_name" in self.model_fields:
12091
users = users.order_by(Lower("display_name"))
12192
# == custom code end
12293

123-
if self.get_ordering() == "username":
124-
users = users.order_by(User.USERNAME_FIELD)
94+
return users
12595

126-
if self.get_ordering() == "name":
127-
users = users.order_by(Lower("display_name"))
96+
def order_queryset(self, queryset):
97+
if self.ordering == "name":
98+
return queryset.order_by(Lower("display_name"))
99+
if self.ordering == "-name":
100+
return queryset.order_by(Lower("-display_name"))
101+
return super().order_queryset(queryset)
128102

129-
# == custom code
130-
if not self.group:
131-
filterset_class = self.get_filterset_class()
132-
users = filterset_class(
133-
self.request.GET, queryset=users, request=self.request
134-
).qs
135-
# == end custom code
136103

137-
return users
104+
class CustomUserViewSet(WagtailUserViewSet):
105+
filterset_class = UserFilterSet
106+
index_view_class = CustomUserIndexView
107+
108+
def get_form_class(self, for_update=False):
109+
if for_update:
110+
return CustomUserEditForm
111+
return CustomUserCreationForm
138112

139113

140114
class CustomGroupIndexView(GroupIndexView):
@@ -167,13 +141,29 @@ def get_queryset(self):
167141
return custom_groups
168142

169143

170-
class CustomGroupViewSet(GroupViewSet):
144+
class CustomGroupEditView(GroupEditView):
145+
@cached_property
146+
def header_buttons(self):
147+
return [
148+
HeaderButton(
149+
gettext("View users in this group"),
150+
url=set_query_params(
151+
reverse("wagtailusers_users:index"),
152+
{"roles": self.object.pk},
153+
),
154+
icon_name="user",
155+
)
156+
]
157+
158+
159+
class CustomGroupViewSet(WagtailGroupViewSet):
171160
"""
172161
Overriding the wagtail.users.views.groups.GroupViewSet just to use custom users view(index)
173162
when getting all users for a group.
174163
"""
175164

176165
index_view_class = CustomGroupIndexView
166+
edit_view_class = CustomGroupEditView
177167

178168
@property
179169
def users_view(self):

hypha/apply/users/forms.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,13 @@ def __init__(self, *args, **kwargs):
9191
super().__init__(*args, **kwargs)
9292

9393
# HACK: Wagtail admin doesn't work with custom User models that do not have first/last name.
94+
self.fields["first_name"].label = ""
95+
self.fields["first_name"].required = False
9496
self.fields["first_name"].widget = forms.HiddenInput(
9597
attrs={"value": "Not used - see full_name"}
9698
)
99+
self.fields["last_name"].label = ""
100+
self.fields["last_name"].required = False
97101
self.fields["last_name"].widget = forms.HiddenInput(
98102
attrs={"value": "Not used - see full_name"}
99103
)
@@ -130,13 +134,12 @@ def label_from_instance(self, group_obj):
130134
)
131135
if help_text:
132136
return mark_safe(
133-
f'{group_obj.name}<p class="group-help-text">{help_text}</p>'
137+
f'<div><div>{group_obj.name}</div><div class="help">{help_text}</div></div>'
134138
)
135139
return group_obj.name
136140

137141

138142
class CustomUserEditForm(CustomUserAdminFormBase, UserEditForm):
139-
# pass
140143
"""
141144
A custom UserEditForm used to provide custom fields (ie. custom group fields)
142145
"""
@@ -149,6 +152,9 @@ def __init__(self, *args, **kwargs):
149152
self.fields["groups"]
150153
)
151154

155+
class Meta(UserEditForm.Meta):
156+
fields = UserEditForm.Meta.fields | {"full_name", "slack"}
157+
152158

153159
class CustomUserCreationForm(CustomUserAdminFormBase, UserCreationForm):
154160
def __init__(self, register_view=False, request=None, *args, **kwargs):
@@ -168,6 +174,9 @@ def __init__(self, register_view=False, request=None, *args, **kwargs):
168174
self.fields["groups"]
169175
)
170176

177+
class Meta(UserCreationForm.Meta):
178+
fields = UserCreationForm.Meta.fields | {"full_name", "slack"}
179+
171180

172181
class ProfileForm(forms.ModelForm):
173182
class Meta:
Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,6 @@
11
{% extends "wagtailusers/users/create.html" %}
2-
{% load static %}
32

4-
{% block fields %}
5-
{% if form.separate_username_field %}
6-
<li>{% include "wagtailadmin/shared/field.html" with field=form.username_field %}</li>
7-
{% endif %}
8-
<li>{% include "wagtailadmin/shared/field.html" with field=form.email %}</li>
3+
{% block extra_fields %}
94
<li>{% include "wagtailadmin/shared/field.html" with field=form.full_name %}</li>
10-
11-
{% comment %}
12-
First/last name hidden input with dummy values because.. Wagtail admin
13-
See hypha.apply.users.forms.CustomUserCreationForm
14-
{% endcomment %}
15-
{{ form.first_name }}
16-
{{ form.last_name }}
17-
18-
{% if form.password1 %}
19-
<li>{% include "wagtailadmin/shared/field.html" with field=form.password1 %}</li>
20-
{% endif %}
21-
{% if form.password2 %}
22-
<li>{% include "wagtailadmin/shared/field.html" with field=form.password2 %}</li>
23-
{% endif %}
24-
{% if form.is_active %}
25-
<li>{% include "wagtailadmin/shared/field.html" with field=form.is_active %}</li>
26-
{% endif %}
27-
{% endblock fields %}
28-
29-
{% block extra_css %}
30-
<link rel="stylesheet" href="{% static 'css/wagtail_groups_list.css' %}">
31-
{% endblock %}
5+
<li>{% include "wagtailadmin/shared/field.html" with field=form.slack %}</li>
6+
{% endblock extra_fields %}
Lines changed: 4 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,6 @@
1-
<!-- Override the Wagtail's user edit template to add a custom 'Disable 2FA' button to account section -->
21
{% extends "wagtailusers/users/edit.html" %}
3-
{% load wagtailimages_tags %}
4-
{% load users_tags %}
5-
{% load static %}
6-
{% load i18n %}
7-
{% block content %}
82

9-
{% trans "Editing" as editing_str %}
10-
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=user.get_username merged=1 icon="user" %}
11-
12-
<style>
13-
{# fix for checkbox alignment #}
14-
input[type=checkbox] {
15-
margin-bottom: .4rem;
16-
}
17-
</style>
18-
19-
<div class="w-tabs" data-tabs>
20-
<div class="w-tabs__wrapper">
21-
<div role="tablist" class="w-tabs__list">
22-
{% trans "Account" as account_text %}
23-
{% include 'wagtailadmin/shared/tabs/tab_nav_link.html' with tab_id='account' title=account_text %}
24-
{% trans "Roles" as roles_text %}
25-
{% include 'wagtailadmin/shared/tabs/tab_nav_link.html' with tab_id='roles' title=roles_text %}
26-
</div>
27-
</div>
28-
29-
<form action="{% url 'wagtailusers_users:edit' user.pk %}" method="POST" novalidate{% if form.is_multipart %} enctype="multipart/form-data"{% endif %}>
30-
<div class="tab-content">
31-
{% csrf_token %}
32-
33-
<section
34-
id="tab-account"
35-
class="w-tabs__panel"
36-
role="tabpanel"
37-
hidden
38-
aria-labelledby="tab-label-account"
39-
>
40-
<ul class="fields">
41-
{% block fields %}
42-
<!-- Block Fields are overridden to show fields as per the requirement -->
43-
{% if form.separate_username_field %}
44-
<li>{% include "wagtailadmin/shared/field.html" with field=form.username_field %}</li>
45-
{% endif %}
46-
<li>{% include "wagtailadmin/shared/field.html" with field=form.email %}</li>
47-
<li>{% include "wagtailadmin/shared/field.html" with field=form.full_name %}</li>
48-
{% block extra_fields %}{% endblock extra_fields %}
49-
50-
{% comment %}
51-
First/last name hidden input with dummy values because.. Wagtail admin
52-
See hypha.apply.users.forms.CustomUserEditForm
53-
{% endcomment %}
54-
{{ form.first_name }}
55-
{{ form.last_name }}
56-
57-
{% if form.password1 %}
58-
<li>{% include "wagtailadmin/shared/field.html" with field=form.password1 %}</li>
59-
{% endif %}
60-
{% if form.password2 %}
61-
<li>{% include "wagtailadmin/shared/field.html" with field=form.password2 %}</li>
62-
{% endif %}
63-
{% if form.is_active %}
64-
<li>{% include "wagtailadmin/shared/field.html" with field=form.is_active %}</li>
65-
{% endif %}
66-
67-
{% endblock fields %}
68-
<li>
69-
<input type="submit" value="{% trans 'Save' %}" class="button"/>
70-
{% if can_delete %}
71-
<a href="{% url 'wagtailusers_users:delete' user.pk %}" class="button no">{% trans "Delete user" %}</a>
72-
{% endif %}
73-
<!-- Add a custom button to user account edit form -->
74-
{% user_2fa_enabled user as is_2fa_enabled %}
75-
{% if is_2fa_enabled %}
76-
<a href="{% url 'users:admin_disable' user.pk %}" class="button">{% trans "Disable 2FA" %}</a>
77-
{% else %}
78-
<button type="button" title="{% trans "This account do not have 2FA enabled." %}" class="button" disabled>{% trans "2FA already disabled" %}</button>
79-
{% endif %}
80-
</li>
81-
</ul>
82-
</section>
83-
<section
84-
id="tab-roles"
85-
class="w-tabs__panel"
86-
role="tabpanel"
87-
hidden
88-
aria-labelledby="tab-label-roles"
89-
>
90-
<ul class="fields">
91-
{% if form.is_superuser %}
92-
<li>{% include "wagtailadmin/shared/field.html" with field=form.is_superuser %}</li>
93-
{% endif %}
94-
95-
<li>{% include "wagtailadmin/shared/field.html" with field=form.groups %}</li>
96-
<li>
97-
<input type="submit" value="{% trans 'Save' %}" class="button"/>
98-
{% if can_delete %}
99-
<a href="{% url 'wagtailusers_users:delete' user.pk %}" class="button no">{% trans "Delete user" %}</a>
100-
{% endif %}
101-
</li>
102-
</ul>
103-
</section>
104-
</div>
105-
</form>
106-
</div>
107-
{% endblock %}
108-
109-
{% block extra_css %}
110-
<link rel="stylesheet" href="{% static 'css/wagtail_groups_list.css' %}">
111-
{{ block.super }}
112-
{% endblock %}
113-
114-
{% block extra_js %}
115-
{{ block.super }}
116-
{% include "wagtailadmin/pages/_editor_js.html" %}
117-
{{ form.media.js }}
118-
{% endblock %}
3+
{% block extra_fields %}
4+
<li>{% include "wagtailadmin/shared/field.html" with field=form.full_name %}</li>
5+
<li>{% include "wagtailadmin/shared/field.html" with field=form.slack %}</li>
6+
{% endblock extra_fields %}

hypha/apply/users/templates/wagtailusers/users/index.html

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)