feat(association): affiche le menu Gérer… que sur les détails

pull/105/head
Jérôme Lebleu 2019-09-12 15:14:14 +02:00
Parent ded158f5b1
révision 361e419268
3 fichiers modifiés avec 144 ajouts et 152 suppressions

Voir le fichier

@ -5,6 +5,7 @@ import pytest
from bs4 import BeautifulSoup as bs
from benevalibre.association.models import Association
from benevalibre.association.views import get_management_buttons
from benevalibre.utils.tests import (
ManagerOnlyViewMixin,
count_text_in_content,
@ -12,6 +13,43 @@ from benevalibre.utils.tests import (
)
@pytest.mark.django_db
class TestAssociationManagementButtons:
def test_foreign(self, association, foreign):
buttons = get_management_buttons(association, foreign)
assert len(buttons) == 0
def test_manager(self, association, user, manager):
buttons = get_management_buttons(association, user)
assert len(buttons) == 7
def test_superuser(self, association, superuser):
buttons = get_management_buttons(association, superuser)
assert len(buttons) == 1
@pytest.mark.parametrize(
'role_name, expected',
[('Bénévole', 0), ('Animat⋅eur⋅rice', 5), ('Dirigeant', 7)],
)
def test_role(self, association, user, engagement, role_name, expected):
engagement = association.get_engagement(user)
engagement.role = association.role_set.get(name=role_name)
engagement.save()
assert len(get_management_buttons(association, user)) == expected
def test_role_list_users(self, association, user, engagement):
role = association.role_set.get_benevole()
role.list_users = True
role.save()
engagement = association.get_engagement(user)
engagement.role = role
engagement.save()
assert len(get_management_buttons(association, user)) == 1
@pytest.mark.django_db
class TestAssosiationIndex:
url = reverse_lazy('association:index')
@ -154,76 +192,28 @@ class TestAssosiationDetail:
)
assert response.status_code == expected
@pytest.mark.parametrize(
'use, expected', [(None, 0), ('user', 7), ('staff', 1), ('foreign', 0)]
)
def test_management_buttons(
self,
client,
association,
user,
superuser,
foreign,
manager,
use,
expected,
):
if use == 'staff':
client.force_login(superuser)
elif use == 'foreign':
client.force_login(foreign)
elif use:
client.force_login(user)
def test_titlebuttons_foreign(self, client, association, foreign):
client.force_login(foreign)
response = client.get(
reverse('association:detail', args=[association.id])
)
assert response.status_code == 200
assert not count_text_in_content(response, "title-buttons")
assert not count_text_in_content(response, "Gérer")
buttons = (
bs(response.content, 'html.parser')
.find(id='main-menu')
.find_all('a', class_='dropdown-item capabilities')
)
assert len(buttons) == expected
@pytest.mark.parametrize(
'userole, expected',
[
('Bénévole', None),
('Bénévole++', 1),
('Animat⋅eur⋅rice', 5),
('Dirigeant', 7),
],
)
def test_manage_features(
self, client, association, user, engagement, userole, expected
):
def test_titlebuttons_manager(self, client, association, user, manager):
client.force_login(user)
# étends le role Bénévole
if userole == 'Bénévole++':
userole = 'Bénévole'
role = association.role_set.get_benevole()
role.list_users = True
role.save()
# définis le role du bénévole
engagement = association.get_engagement(user)
engagement.role = association.role_set.get(name=userole)
engagement.save()
response = client.get(
reverse('association:detail', args=[association.id])
)
assert response.status_code == 200
assert count_text_in_content(response, "title-buttons")
assert count_text_in_content(response, "Gérer")
buttons = (
bs(response.content, 'html.parser')
.find(id='main-menu')
.find_all('a', class_='dropdown-item capabilities')
.find(class_='title-buttons')
.find_all('a', class_='dropdown-item')
)
assert bool(buttons) == bool(expected) or len(buttons) == expected
assert len(buttons) == 7
@pytest.mark.django_db
@ -322,8 +312,8 @@ class TestAssosiationCreate:
buttons = (
bs(response.content, 'html.parser')
.find(id='main-menu')
.find_all('a', class_='dropdown-item capabilities')
.find(class_='title-buttons')
.find_all('a', class_='dropdown-item')
)
assert len(buttons) == 7

Voir le fichier

@ -14,86 +14,89 @@ from cruditor.views import (
)
from benevalibre.base.tables import EngagementIndexTable
from benevalibre.utils.html import fa_icon
from benevalibre.utils.views import CruditorPageMixin, PageMixin
from . import forms, models, tables
class AssociationManageMenu:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if hasattr(self, 'association'):
association = self.association
elif hasattr(self, 'object') and isinstance(
self.object, models.Association
):
association = self.object
else:
raise NotImplementedError("No way to get any related association")
def get_management_buttons(association, user):
"""
Return the management actions that `user` has on `association` as a list
of buttons - e.g. to be displayed in the title buttons.
"""
buttons = []
capabilities = []
if association.can_manage_engagements(self.request.user):
capabilities.append(
[
'users',
"Gérer les bénévoles",
'association:engagement:index',
]
)
elif association.can_list_users(self.request.user):
capabilities.append(
['users', "Voir les bénévoles", 'base:association:user']
)
if association.can_manage_benevalos(self.request.user):
capabilities.append(
[
'gift',
"Gérer les bénévolats",
'base:association:benevalo:index',
]
)
if association.can_manage_levels(self.request.user):
capabilities.append(
[
'tachometer',
"Gérer les niveaux de bénévolat",
'association:level:index',
]
)
if association.can_manage_projects(self.request.user):
capabilities.append(
[
'wrench',
"Gérer les projets de l'association",
'association:project:index',
]
)
if association.can_manage_categories(self.request.user):
capabilities.append(
[
'tags',
"Gérer les catégories de bénévolat",
'association:category:index',
]
)
if association.can_manage_roles(self.request.user):
capabilities.append(
[
'key-modern',
"Gérer les roles de l'association",
'association:role:index',
]
)
if association.can_manage_association(self.request.user):
capabilities.append(
['edit', "Modifier l'association", 'association:update']
)
context['capabilities'] = capabilities
context['association'] = association
return context
def _reverse(viewname):
return reverse(viewname, args=[association.id])
if association.can_manage_engagements(user):
buttons.append(
{
'label': fa_icon('users', "Gérer les bénévoles"),
'url': _reverse('association:engagement:index'),
}
)
elif association.can_list_users(user):
buttons.append(
{
'label': fa_icon('users', "Voir les bénévoles"),
'url': _reverse('base:association:user'),
}
)
if association.can_manage_benevalos(user):
buttons.append(
{
'label': fa_icon('gift', "Gérer les bénévolats"),
'url': _reverse('base:association:benevalo:index'),
}
)
if association.can_manage_levels(user):
buttons.append(
{
'label': fa_icon(
'tachometer', "Gérer les niveaux de bénévolat"
),
'url': _reverse('association:level:index'),
}
)
if association.can_manage_projects(user):
buttons.append(
{
'label': fa_icon(
'wrench', "Gérer les projets de l'association"
),
'url': _reverse('association:project:index'),
}
)
if association.can_manage_categories(user):
buttons.append(
{
'label': fa_icon('tags', "Gérer les catégories de bénévolat"),
'url': _reverse('association:category:index'),
}
)
if association.can_manage_roles(user):
buttons.append(
{
'label': fa_icon(
'key-modern', "Gérer les roles de l'association"
),
'url': _reverse('association:role:index'),
}
)
if association.can_manage_association(user):
buttons.append(
{
'label': fa_icon('edit', "Modifier l'association"),
'url': _reverse('association:update'),
}
)
return buttons
class AssociationRelatedMixin(AssociationManageMenu):
class AssociationRelatedMixin:
"""
Mixin to apply to the views related to an existing `Association`. The
object with the id given by the `association` keyword argument will be
@ -242,7 +245,7 @@ class AssociationCreate(CruditorPageMixin, CruditorAddView):
return reverse('association:detail', args=[self.object.pk])
class AssociationDetail(AssociationManageMenu, PageMixin, DetailView):
class AssociationDetail(PageMixin, DetailView):
template_name = 'association/association_detail.html'
def get_queryset(self):
@ -253,10 +256,21 @@ class AssociationDetail(AssociationManageMenu, PageMixin, DetailView):
def get_title(self):
return self.object.name
def get_titlebuttons(self):
management_buttons = get_management_buttons(
self.object, self.request.user
)
if management_buttons:
return [
{
'label': fa_icon('gear', "Gérer…"),
'submenu': management_buttons,
}
]
return []
class AssociationUpdate(
AssociationManageMenu, CruditorPageMixin, CruditorChangeView
):
class AssociationUpdate(CruditorPageMixin, CruditorChangeView):
model = models.Association
form_class = forms.UpdateForm
title = "Modifier une association"
@ -281,9 +295,7 @@ class AssociationUpdate(
return super().form_valid(form)
class AssociationDelete(
AssociationManageMenu, CruditorPageMixin, CruditorDeleteView
):
class AssociationDelete(CruditorPageMixin, CruditorDeleteView):
model = models.Association
title = "Supprimer une association"

Voir le fichier

@ -19,7 +19,6 @@ from django_tables2.export.views import ExportMixin
from benevalibre.association import models as asso_models
from benevalibre.association.views import (
AssociationManageMenu,
AssociationRelatedFormMixin,
AssociationRelatedMixin,
)
@ -76,11 +75,7 @@ class Home(PageMixin, TemplateView):
class AssociationEngage(
AssociationRelatedMixin,
AssociationManageMenu,
CruditorPageMixin,
SuccessMessageMixin,
FormView,
AssociationRelatedMixin, CruditorPageMixin, SuccessMessageMixin, FormView
):
"""
Pour s'engager comme bénévole auprès d'une association, il suffit de
@ -261,10 +256,7 @@ class EngagementIndex(
class AssociatedEngagementReadOnlyIndex(
AssociationRelatedMixin,
AssociationManageMenu,
CruditorPageMixin,
CruditorListView,
AssociationRelatedMixin, CruditorPageMixin, CruditorListView
):
model = asso_models.Engagement
table_class = tables.EngagementReadOnlyIndexTable
@ -290,7 +282,7 @@ class AssociatedFormMixin:
return kwargs
class AssociatedBenevaloMixin(AssociationRelatedMixin, AssociationManageMenu):
class AssociatedBenevaloMixin(AssociationRelatedMixin):
model = Benevalo
def dispatch(self, request, *args, **kwargs):
@ -395,7 +387,6 @@ class AssociatedEngagedBenevaloModerationMixin(BenevaloModerationMixin):
class AssociatedEngagedBenevaloIndex(
AssociationRelatedMixin,
AssociationManageMenu,
AssociatedEngagedBenevaloModerationMixin,
ExportTable,
CruditorPageMixin,
@ -472,7 +463,6 @@ class AssociatedSelfBenevaloMixin(AssociationRelatedMixin):
class AssociatedSelfBenevaloIndex(
AssociationRelatedMixin,
AssociationManageMenu,
AssociatedBenevaloModerationMixin,
ExportTable,
CruditorPageMixin,