Merge branch 'kerl/bds_update_user' into 'master'
BDS: vue pour modifier un compte existant See merge request klub-dev-ens/gestioCOF!430
This commit is contained in:
commit
b24935b938
9 changed files with 238 additions and 3 deletions
18
bds/forms.py
Normal file
18
bds/forms.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
from django import forms
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
|
from bds.models import BDSProfile
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
class UserForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = User
|
||||||
|
fields = ["email", "first_name", "last_name"]
|
||||||
|
|
||||||
|
|
||||||
|
class ProfileForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = BDSProfile
|
||||||
|
exclude = ["user"]
|
|
@ -2,4 +2,4 @@ from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||||
|
|
||||||
|
|
||||||
class StaffRequiredMixin(PermissionRequiredMixin):
|
class StaffRequiredMixin(PermissionRequiredMixin):
|
||||||
permission_required = "bds:is_team"
|
permission_required = "bds.is_team"
|
||||||
|
|
|
@ -26,15 +26,16 @@ nav a, nav a img {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
input[type="text"], input[type="email"] {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
border: 0;
|
||||||
|
padding: 5px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#search_autocomplete {
|
#search_autocomplete {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
width: 480px;
|
width: 480px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: 0;
|
|
||||||
padding: 10px 10px;
|
padding: 10px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,3 +81,66 @@ input[type="text"] {
|
||||||
.autocomplete-value, .autocomplete-new, .autocomplete-more {
|
.autocomplete-value, .autocomplete-new, .autocomplete-more {
|
||||||
background: white;
|
background: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- Forms --- */
|
||||||
|
|
||||||
|
.form-wrapper {
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 1em;
|
||||||
|
max-width: 900px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
table, tbody {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
width: 50%;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
width: 50%;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="submit"] {
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin-top: 1em;
|
||||||
|
width: 300px;
|
||||||
|
background: #3e2263;
|
||||||
|
color: white;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
border: solid #3e2263;
|
||||||
|
padding: 0.2em 0.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="submit"]:hover {
|
||||||
|
border-color: #e8554e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Message styling --- */
|
||||||
|
|
||||||
|
.error {
|
||||||
|
background: red;
|
||||||
|
color: white;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.5em 0;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.2em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success {
|
||||||
|
background: green;
|
||||||
|
color: white;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.5em 0;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.2em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,18 @@
|
||||||
<body>
|
<body>
|
||||||
{% include "bds/nav.html" %}
|
{% include "bds/nav.html" %}
|
||||||
|
|
||||||
|
{% if messages %}
|
||||||
|
{% for message in messages %}
|
||||||
|
<p class="{{ message.level_tag }}">
|
||||||
|
{% if 'safe' in message.tags %}
|
||||||
|
{{ message|safe }}
|
||||||
|
{% else %}
|
||||||
|
{{ message }}
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
27
bds/templates/bds/user_update.html
Normal file
27
bds/templates/bds/user_update.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{% extends "bds/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% for error in user_form.non_field_errors %}
|
||||||
|
<p class="error">{{ error }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
{% for error in profile_form.non_field_errors %}
|
||||||
|
<p class="error">{{ error }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<div class="form-wrapper">
|
||||||
|
<form action="" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
{{ user_form.as_table }}
|
||||||
|
{{ profile_form.as_table }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<input type="submit" value="Enregistrer">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
0
bds/tests/__init__.py
Normal file
0
bds/tests/__init__.py
Normal file
65
bds/tests/test_views.py
Normal file
65
bds/tests/test_views.py
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.test import Client, TestCase
|
||||||
|
from django.urls import reverse, reverse_lazy
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
def give_bds_buro_permissions(user: User) -> None:
|
||||||
|
perm = Permission.objects.get(content_type__app_label="bds", codename="is_team")
|
||||||
|
user.user_permissions.add(perm)
|
||||||
|
|
||||||
|
|
||||||
|
def login_url(next=None):
|
||||||
|
login_url = reverse_lazy(settings.LOGIN_URL)
|
||||||
|
if next is None:
|
||||||
|
return login_url
|
||||||
|
else:
|
||||||
|
return "{}?next={}".format(login_url, next)
|
||||||
|
|
||||||
|
|
||||||
|
class TestRegistrationView(TestCase):
|
||||||
|
@mock.patch("gestioncof.signals.messages")
|
||||||
|
def test_get_autocomplete(self, mock_messages):
|
||||||
|
user = User.objects.create_user(username="toto")
|
||||||
|
url = reverse("bds:autocomplete") + "?q=foo"
|
||||||
|
client = Client()
|
||||||
|
|
||||||
|
# Anonymous GET
|
||||||
|
resp = client.get(url)
|
||||||
|
self.assertRedirects(resp, login_url(next=url))
|
||||||
|
|
||||||
|
# Logged-in but unprivileged GET
|
||||||
|
client.force_login(user)
|
||||||
|
resp = client.get(url)
|
||||||
|
self.assertEquals(resp.status_code, 403)
|
||||||
|
|
||||||
|
# Burô user GET
|
||||||
|
give_bds_buro_permissions(user)
|
||||||
|
resp = client.get(url)
|
||||||
|
self.assertEquals(resp.status_code, 200)
|
||||||
|
|
||||||
|
@mock.patch("gestioncof.signals.messages")
|
||||||
|
def test_get(self, mock_messages):
|
||||||
|
user = User.objects.create_user(username="toto")
|
||||||
|
url = reverse("bds:user.update", args=(user.id,))
|
||||||
|
print(url)
|
||||||
|
client = Client()
|
||||||
|
|
||||||
|
# Anonymous GET
|
||||||
|
resp = client.get(url)
|
||||||
|
self.assertRedirects(resp, login_url(next=url))
|
||||||
|
|
||||||
|
# Logged-in but unprivileged GET
|
||||||
|
client.force_login(user)
|
||||||
|
resp = client.get(url)
|
||||||
|
self.assertEquals(resp.status_code, 403)
|
||||||
|
|
||||||
|
# Burô user GET
|
||||||
|
give_bds_buro_permissions(user)
|
||||||
|
resp = client.get(url)
|
||||||
|
self.assertEquals(resp.status_code, 200)
|
|
@ -6,4 +6,5 @@ app_name = "bds"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", views.Home.as_view(), name="home"),
|
path("", views.Home.as_view(), name="home"),
|
||||||
path("autocomplete", views.BDSAutocompleteView.as_view(), name="autocomplete"),
|
path("autocomplete", views.BDSAutocompleteView.as_view(), name="autocomplete"),
|
||||||
|
path("user/update/<int:pk>", views.UserUpdateView.as_view(), name="user.update"),
|
||||||
]
|
]
|
||||||
|
|
48
bds/views.py
48
bds/views.py
|
@ -1,9 +1,16 @@
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
from bds.autocomplete import bds_search
|
from bds.autocomplete import bds_search
|
||||||
|
from bds.forms import ProfileForm, UserForm
|
||||||
from bds.mixins import StaffRequiredMixin
|
from bds.mixins import StaffRequiredMixin
|
||||||
from shared.views import AutocompleteView
|
from shared.views import AutocompleteView
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class BDSAutocompleteView(StaffRequiredMixin, AutocompleteView):
|
class BDSAutocompleteView(StaffRequiredMixin, AutocompleteView):
|
||||||
template_name = "bds/search_results.html"
|
template_name = "bds/search_results.html"
|
||||||
|
@ -12,3 +19,44 @@ class BDSAutocompleteView(StaffRequiredMixin, AutocompleteView):
|
||||||
|
|
||||||
class Home(StaffRequiredMixin, TemplateView):
|
class Home(StaffRequiredMixin, TemplateView):
|
||||||
template_name = "bds/home.html"
|
template_name = "bds/home.html"
|
||||||
|
|
||||||
|
|
||||||
|
class UserUpdateView(StaffRequiredMixin, TemplateView):
|
||||||
|
template_name = "bds/user_update.html"
|
||||||
|
|
||||||
|
def get_user(self):
|
||||||
|
return get_object_or_404(User, pk=self.kwargs["pk"])
|
||||||
|
|
||||||
|
def get_user_form(self, data=None):
|
||||||
|
return UserForm(prefix="u", instance=self.user, data=data)
|
||||||
|
|
||||||
|
def get_profile_form(self, data=None):
|
||||||
|
profile = getattr(self.user, "bds", None)
|
||||||
|
return ProfileForm(prefix="p", instance=profile, data=data)
|
||||||
|
|
||||||
|
def get_context_data(self, user_form=None, profile_form=None, **kwargs):
|
||||||
|
return {
|
||||||
|
"user_form": user_form or self.get_user_form(),
|
||||||
|
"profile_form": profile_form or self.get_profile_form(),
|
||||||
|
}
|
||||||
|
|
||||||
|
def get(self, *args, **kwargs):
|
||||||
|
self.user = self.get_user()
|
||||||
|
return super().get(*args, **kwargs)
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
self.user = self.get_user()
|
||||||
|
user_form = self.get_user_form(data=request.POST)
|
||||||
|
profile_form = self.get_profile_form(data=request.POST)
|
||||||
|
|
||||||
|
if user_form.is_valid() and profile_form.is_valid():
|
||||||
|
self.user = user_form.save()
|
||||||
|
profile = profile_form.save(commit=False)
|
||||||
|
profile.user = self.user
|
||||||
|
profile.save()
|
||||||
|
messages.success(self.request, _("Profil mis à jour avec succès"))
|
||||||
|
|
||||||
|
else:
|
||||||
|
messages.error(self.request, _("Veuillez corriger les erreurs ci-dessous"))
|
||||||
|
|
||||||
|
return self.render_to_response(self.get_context_data(user_form, profile_form))
|
||||||
|
|
Loading…
Reference in a new issue