clubs: Handle bulk add of users in clubs and refresh of the form handling

This commit is contained in:
Antoine Bartuccio 2019-04-24 03:10:42 +02:00
parent e8ee9122f9
commit d5ad2c5141
Signed by: klmp200
GPG Key ID: E7245548C53F904B
3 changed files with 121 additions and 85 deletions

View File

@ -11,7 +11,7 @@
<td>{% trans %}Since{% endtrans %}</td> <td>{% trans %}Since{% endtrans %}</td>
</thead> </thead>
<tbody> <tbody>
{% for m in club.members.filter(end_date=None).order_by('-role').all() %} {% for m in members %}
<tr> <tr>
<td>{{ user_profile_link(m.user) }}</td> <td>{{ user_profile_link(m.user) }}</td>
<td>{{ settings.SITH_CLUB_ROLES[m.role] }}</td> <td>{{ settings.SITH_CLUB_ROLES[m.role] }}</td>
@ -30,6 +30,3 @@
<p><input type="submit" value="{% trans %}Add{% endtrans %}" /></p> <p><input type="submit" value="{% trans %}Add{% endtrans %}" /></p>
</form> </form>
{% endblock %} {% endblock %}

View File

@ -33,7 +33,7 @@ from django.core.urlresolvers import reverse, reverse_lazy
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext as _t from django.utils.translation import ugettext as _t
from ajax_select.fields import AutoCompleteSelectField from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultipleField
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
@ -44,6 +44,7 @@ from core.views import (
CanEditPropMixin, CanEditPropMixin,
TabedViewMixin, TabedViewMixin,
PageEditViewBase, PageEditViewBase,
DetailFormView,
) )
from core.views.forms import SelectDate, SelectDateTime from core.views.forms import SelectDate, SelectDateTime
from club.models import Club, Membership, Mailing, MailingSubscription from club.models import Club, Membership, Mailing, MailingSubscription
@ -305,7 +306,7 @@ class ClubToolsView(ClubTabsMixin, CanEditMixin, DetailView):
current_tab = "tools" current_tab = "tools"
class ClubMemberForm(forms.ModelForm): class ClubMemberForm(forms.Form):
""" """
Form handling the members of a club Form handling the members of a club
""" """
@ -313,24 +314,68 @@ class ClubMemberForm(forms.ModelForm):
error_css_class = "error" error_css_class = "error"
required_css_class = "required" required_css_class = "required"
class Meta: users = AutoCompleteSelectMultipleField(
model = Membership "users",
fields = ["user", "role", "start_date", "description"] label=_("Users to add"),
widgets = {"start_date": SelectDate} help_text=_("Search users to add (one or more)."),
required=True,
user = AutoCompleteSelectField(
"users", required=True, label=_("Select user"), help_text=None
) )
def save(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.club = kwargs.pop("club")
self.request_user = kwargs.pop("request_user")
super(ClubMemberForm, self).__init__(*args, **kwargs)
# Using a ModelForm forces a save and we don't want that
# We want the view to process the model creation since they are multiple users
self.fields.update(
forms.fields_for_model(
Membership,
fields=("role", "start_date", "description"),
widgets={"start_date": SelectDate},
)
)
if not self.request_user.is_root:
self.fields.pop("start_date")
def clean_users(self):
""" """
Overloaded to return the club, and not to a Membership object that has no view Check that the user is not trying to add an user already in the club
""" """
super(ClubMemberForm, self).save(*args, **kwargs) cleaned_data = super(ClubMemberForm, self).clean()
return self.instance.club users = []
for user_id in cleaned_data["users"]:
user = User.objects.filter(id=user_id).first()
if not user:
raise forms.ValidationError(
_("One of the selected users doesn't exist", code="invalid")
)
users.append(user)
if self.club.get_membership_for(user):
raise forms.ValidationError(
_("You can not add the same user twice"), code="invalid"
)
return users
def clean(self):
"""
Check user rights
"""
cleaned_data = super(ClubMemberForm, self).clean()
request_user = self.request_user
membership = self.club.get_membership_for(request_user)
print(request_user.is_root)
if not (
cleaned_data["role"] <= SITH_MAXIMUM_FREE_ROLE
or (membership is not None and membership.role >= cleaned_data["role"])
or request_user.is_board_member
or request_user.is_root
):
raise forms.ValidationError(_("You do not have the permission to do that"))
return cleaned_data
class ClubMembersView(ClubTabsMixin, CanViewMixin, UpdateView): class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView):
""" """
View of a club's members View of a club's members
""" """
@ -341,52 +386,39 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, UpdateView):
template_name = "club/club_members.jinja" template_name = "club/club_members.jinja"
current_tab = "members" current_tab = "members"
def get_form(self): def get_form_kwargs(self):
""" kwargs = super(ClubMembersView, self).get_form_kwargs()
Here we get a Membership object, but the view handles Club object. kwargs["request_user"] = self.request_user
That's why the save method of ClubMemberForm is overridden. kwargs["club"] = self.get_object()
""" return kwargs
form = super(ClubMembersView, self).get_form()
if ( def get_context_data(self, *args, **kwargs):
"user" in form.data and form.data.get("user") != "" kwargs = super(ClubMembersView, self).get_context_data(*args, **kwargs)
): # Load an existing membership if possible kwargs["members"] = (
form.instance = ( self.get_object().members.filter(end_date=None).order_by("-role").all()
Membership.objects.filter(club=self.object) )
.filter(user=form.data.get("user")) return kwargs
.filter(end_date=None)
.first()
)
if form.instance is None: # Instanciate a new membership
form.instance = Membership(club=self.object, user=self.request.user)
if not self.request.user.is_root:
form.fields.pop("start_date", None)
return form
def form_valid(self, form): def form_valid(self, form):
""" """
Check user rights Check user rights
""" """
user = self.request.user resp = super(ClubMembersView, self).form_valid(form)
ms = self.object.get_membership_for(user)
if ( data = form.clean()
form.cleaned_data["role"] <= SITH_MAXIMUM_FREE_ROLE users = data.pop("users", [])
or (ms is not None and ms.role >= form.cleaned_data["role"]) for user in users:
or user.is_board_member Membership(club=self.get_object(), user=user, **data).save()
or user.is_root return resp
):
form.save()
form = self.form_class()
return super(ModelFormMixin, self).form_valid(form)
else:
form.add_error(None, _("You do not have the permission to do that"))
return self.form_invalid(form)
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
self.request = request self.request_user = request.user
return super(ClubMembersView, self).dispatch(request, *args, **kwargs) return super(ClubMembersView, self).dispatch(request, *args, **kwargs)
def get_success_url(self, **kwargs): def get_success_url(self, **kwargs):
return reverse_lazy("club:club_members", kwargs={"club_id": self.club.id}) return reverse_lazy(
"club:club_members", kwargs={"club_id": self.get_object().id}
)
class ClubOldMembersView(ClubTabsMixin, CanViewMixin, DetailView): class ClubOldMembersView(ClubTabsMixin, CanViewMixin, DetailView):

View File

@ -6,7 +6,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-04-22 14:57+0200\n" "POT-Creation-Date: 2019-04-24 03:06+0200\n"
"PO-Revision-Date: 2016-07-18\n" "PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Skia <skia@libskia.so>\n" "Last-Translator: Skia <skia@libskia.so>\n"
"Language-Team: AE info <ae.info@utbm.fr>\n" "Language-Team: AE info <ae.info@utbm.fr>\n"
@ -177,7 +177,7 @@ msgstr "type de cible"
#: accounting/models.py:313 club/models.py:422 #: accounting/models.py:313 club/models.py:422
#: club/templates/club/club_members.jinja:8 #: club/templates/club/club_members.jinja:8
#: club/templates/club/club_old_members.jinja:8 #: club/templates/club/club_old_members.jinja:8
#: club/templates/club/mailing.jinja:28 club/views.py:111 #: club/templates/club/mailing.jinja:28 club/views.py:112
#: counter/templates/counter/cash_summary_list.jinja:32 #: counter/templates/counter/cash_summary_list.jinja:32
#: counter/templates/counter/stats.jinja:15 #: counter/templates/counter/stats.jinja:15
#: counter/templates/counter/stats.jinja:52 #: counter/templates/counter/stats.jinja:52
@ -386,7 +386,7 @@ msgid "Delete"
msgstr "Supprimer" msgstr "Supprimer"
#: accounting/templates/accounting/bank_account_details.jinja:18 #: accounting/templates/accounting/bank_account_details.jinja:18
#: club/views.py:128 core/views/user.py:205 sas/templates/sas/picture.jinja:86 #: club/views.py:129 core/views/user.py:205 sas/templates/sas/picture.jinja:86
msgid "Infos" msgid "Infos"
msgstr "Infos" msgstr "Infos"
@ -405,7 +405,7 @@ msgstr "Nouveau compte club"
#: accounting/templates/accounting/bank_account_details.jinja:27 #: accounting/templates/accounting/bank_account_details.jinja:27
#: accounting/templates/accounting/bank_account_list.jinja:22 #: accounting/templates/accounting/bank_account_list.jinja:22
#: accounting/templates/accounting/club_account_details.jinja:58 #: accounting/templates/accounting/club_account_details.jinja:58
#: accounting/templates/accounting/journal_details.jinja:89 club/views.py:174 #: accounting/templates/accounting/journal_details.jinja:89 club/views.py:175
#: com/templates/com/news_admin_list.jinja:39 #: com/templates/com/news_admin_list.jinja:39
#: com/templates/com/news_admin_list.jinja:68 #: com/templates/com/news_admin_list.jinja:68
#: com/templates/com/news_admin_list.jinja:115 #: com/templates/com/news_admin_list.jinja:115
@ -1070,8 +1070,8 @@ msgstr "Du"
msgid "To" msgid "To"
msgstr "Au" msgstr "Au"
#: club/templates/club/club_sellings.jinja:5 club/views.py:194 #: club/templates/club/club_sellings.jinja:5 club/views.py:195
#: club/views.py:478 counter/templates/counter/counter_main.jinja:19 #: club/views.py:507 counter/templates/counter/counter_main.jinja:19
#: counter/templates/counter/last_ops.jinja:35 #: counter/templates/counter/last_ops.jinja:35
msgid "Sellings" msgid "Sellings"
msgstr "Ventes" msgstr "Ventes"
@ -1097,7 +1097,7 @@ msgstr "unités"
msgid "Benefit: " msgid "Benefit: "
msgstr "Bénéfice : " msgstr "Bénéfice : "
#: club/templates/club/club_sellings.jinja:21 club/views.py:417 #: club/templates/club/club_sellings.jinja:21 club/views.py:446
#: core/templates/core/user_account_detail.jinja:18 #: core/templates/core/user_account_detail.jinja:18
#: core/templates/core/user_account_detail.jinja:51 #: core/templates/core/user_account_detail.jinja:51
#: counter/templates/counter/cash_summary_list.jinja:33 counter/views.py:168 #: counter/templates/counter/cash_summary_list.jinja:33 counter/views.py:168
@ -1246,60 +1246,71 @@ msgstr "Aucune page n'existe pour ce club"
msgid "Club stats" msgid "Club stats"
msgstr "Statistiques du club" msgstr "Statistiques du club"
#: club/views.py:138 #: club/views.py:139
msgid "Members" msgid "Members"
msgstr "Membres" msgstr "Membres"
#: club/views.py:147 #: club/views.py:148
msgid "Old members" msgid "Old members"
msgstr "Anciens membres" msgstr "Anciens membres"
#: club/views.py:157 core/templates/core/page.jinja:33 #: club/views.py:158 core/templates/core/page.jinja:33
msgid "History" msgid "History"
msgstr "Historique" msgstr "Historique"
#: club/views.py:165 core/templates/core/base.jinja:121 core/views/user.py:228 #: club/views.py:166 core/templates/core/base.jinja:121 core/views/user.py:228
#: sas/templates/sas/picture.jinja:95 trombi/views.py:60 #: sas/templates/sas/picture.jinja:95 trombi/views.py:60
msgid "Tools" msgid "Tools"
msgstr "Outils" msgstr "Outils"
#: club/views.py:185 #: club/views.py:186
msgid "Edit club page" msgid "Edit club page"
msgstr "Éditer la page de club" msgstr "Éditer la page de club"
#: club/views.py:201 #: club/views.py:202
msgid "Mailing list" msgid "Mailing list"
msgstr "Listes de diffusion" msgstr "Listes de diffusion"
#: club/views.py:210 com/views.py:141 #: club/views.py:211 com/views.py:141
msgid "Posters list" msgid "Posters list"
msgstr "Liste d'affiches" msgstr "Liste d'affiches"
#: club/views.py:220 counter/templates/counter/counter_list.jinja:21 #: club/views.py:221 counter/templates/counter/counter_list.jinja:21
#: counter/templates/counter/counter_list.jinja:43 #: counter/templates/counter/counter_list.jinja:43
#: counter/templates/counter/counter_list.jinja:59 #: counter/templates/counter/counter_list.jinja:59
msgid "Props" msgid "Props"
msgstr "Propriétés" msgstr "Propriétés"
#: club/views.py:322 core/views/forms.py:358 counter/views.py:113 #: club/views.py:319
#: trombi/views.py:141 msgid "Users to add"
msgid "Select user" msgstr "Utilisateurs à ajouter"
msgstr "Choisir un utilisateur"
#: club/views.py:381 sas/views.py:129 sas/views.py:195 sas/views.py:286 #: club/views.py:320 core/views/group.py:63
msgid "Search users to add (one or more)."
msgstr "Recherche les utilisateurs à ajouter (un ou plus)."
#: club/views.py:348
msgid "One of the selected users doesn't exist"
msgstr "Un des utilisateurs sélectionné n'existe pas"
#: club/views.py:353 core/views/group.py:82
msgid "You can not add the same user twice"
msgstr "Vous ne pouvez pas ajouter deux fois le même utilisateur"
#: club/views.py:371 sas/views.py:129 sas/views.py:195 sas/views.py:286
msgid "You do not have the permission to do that" msgid "You do not have the permission to do that"
msgstr "Vous n'avez pas la permission de faire cela" msgstr "Vous n'avez pas la permission de faire cela"
#: club/views.py:406 counter/views.py:1481 #: club/views.py:435 counter/views.py:1481
msgid "Begin date" msgid "Begin date"
msgstr "Date de début" msgstr "Date de début"
#: club/views.py:412 com/views.py:85 com/views.py:221 counter/views.py:1487 #: club/views.py:441 com/views.py:85 com/views.py:221 counter/views.py:1487
#: election/views.py:190 subscription/views.py:52 #: election/views.py:190 subscription/views.py:52
msgid "End date" msgid "End date"
msgstr "Date de fin" msgstr "Date de fin"
#: club/views.py:435 core/templates/core/user_stats.jinja:27 #: club/views.py:464 core/templates/core/user_stats.jinja:27
#: counter/views.py:1635 #: counter/views.py:1635
msgid "Product" msgid "Product"
msgstr "Produit" msgstr "Produit"
@ -3507,6 +3518,10 @@ msgstr "Parrain"
msgid "Godchild" msgid "Godchild"
msgstr "Fillot" msgstr "Fillot"
#: core/views/forms.py:358 counter/views.py:113 trombi/views.py:141
msgid "Select user"
msgstr "Choisir un utilisateur"
#: core/views/forms.py:371 core/views/forms.py:389 election/models.py:24 #: core/views/forms.py:371 core/views/forms.py:389 election/models.py:24
#: election/views.py:167 #: election/views.py:167
msgid "edit groups" msgid "edit groups"
@ -3525,14 +3540,6 @@ msgstr "Utilisateurs à retirer du groupe"
msgid "Users to add to group" msgid "Users to add to group"
msgstr "Utilisateurs à ajouter au groupe" msgstr "Utilisateurs à ajouter au groupe"
#: core/views/group.py:63
msgid "Search users to add (one or more)."
msgstr "Recherche les utilisateurs à ajouter (un ou plus)."
#: core/views/group.py:82
msgid "You can not add the same user twice"
msgstr "Vous ne pouvez pas ajouter deux fois le même utilisateur"
#: core/views/user.py:223 trombi/templates/trombi/export.jinja:25 #: core/views/user.py:223 trombi/templates/trombi/export.jinja:25
#: trombi/templates/trombi/user_profile.jinja:11 #: trombi/templates/trombi/user_profile.jinja:11
msgid "Pictures" msgid "Pictures"