From 33b23d38da819e81df3695e421bab406a99f264f Mon Sep 17 00:00:00 2001 From: "J.-S. Caux" <J.S.Caux@uva.nl> Date: Sat, 8 May 2021 20:32:06 +0200 Subject: [PATCH] Add affiliate journal manager permissions and facilities --- affiliates/forms.py | 20 ++++++++++ .../migrations/0004_auto_20210508_2012.py | 17 +++++++++ affiliates/models/journal.py | 5 ++- .../affiliates/affiliatejournal_detail.html | 32 ++++++++++++++++ affiliates/urls.py | 10 +++++ affiliates/views.py | 38 ++++++++++++++++++- 6 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 affiliates/forms.py create mode 100644 affiliates/migrations/0004_auto_20210508_2012.py diff --git a/affiliates/forms.py b/affiliates/forms.py new file mode 100644 index 000000000..0839871ea --- /dev/null +++ b/affiliates/forms.py @@ -0,0 +1,20 @@ +__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from django import forms +from django.contrib.auth.models import User + +from dal import autocomplete + + +class AddAffiliateJournalManagerForm(forms.Form): + user = forms.ModelChoiceField( + queryset=User.objects.all(), + widget=autocomplete.ModelSelect2( + url='/user-autocomplete', + attrs={'data-html': True} + ), + label='', + required=True + ) diff --git a/affiliates/migrations/0004_auto_20210508_2012.py b/affiliates/migrations/0004_auto_20210508_2012.py new file mode 100644 index 000000000..c8752a1d9 --- /dev/null +++ b/affiliates/migrations/0004_auto_20210508_2012.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.16 on 2021-05-08 18:12 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('affiliates', '0003_auto_20210508_1653'), + ] + + operations = [ + migrations.AlterModelOptions( + name='affiliatejournal', + options={'ordering': ['publisher', 'name'], 'permissions': (('manage_journal_content', 'Manage Journal content'),)}, + ), + ] diff --git a/affiliates/models/journal.py b/affiliates/models/journal.py index 989f257e6..aaf90d242 100644 --- a/affiliates/models/journal.py +++ b/affiliates/models/journal.py @@ -22,8 +22,6 @@ class AffiliateJournal(models.Model): max_length=256 ) - # Note that the short name can be just as long as the full name. This is because not all - # journals have abbreviated names in Crossref, and instead return the full journal name. short_name = models.CharField( max_length=256, default="" @@ -40,6 +38,9 @@ class AffiliateJournal(models.Model): 'publisher', 'name' ] + permissions = ( + ('manage_journal_content', 'Manage Journal content'), + ) def __str__(self): return self.name diff --git a/affiliates/templates/affiliates/affiliatejournal_detail.html b/affiliates/templates/affiliates/affiliatejournal_detail.html index 809358b39..5b0b65826 100644 --- a/affiliates/templates/affiliates/affiliatejournal_detail.html +++ b/affiliates/templates/affiliates/affiliatejournal_detail.html @@ -12,6 +12,34 @@ <h2 class="highlight">Affiliate Journal: {{ object }}</h2> + {% if perms.affiliates.can_edit_affiliatedjournal %} + <h3 class="highlight">Journal managers</h3> + <div class="row"> + <div class="col-lg-6"> + <h4>Add manager</h4> + <form action="{% url 'affiliates:journal_add_manager' slug=object.slug %}" method="post"> + {% csrf_token %} + {{ add_manager_form }} + <input type="submit" value="Submit" class="btn btn-primary"> + </form> + </div> + <div class="col-lg-6"> + <h4>Current list of managers</h4> + <ul> + {% for manager in journal_managers.all %} + <li>{{ manager.last_name }}, {{ manager.first_name }}  + <a href="{% url 'affiliates:journal_remove_manager' slug=object.slug user_id=manager.pk %}"> + <span class="text-danger">{% include 'bi/x-square-fill.html' %}</span> + </a> + </li> + {% empty %} + <li>No managers found</li> + {% endfor %} + </ul> + </div> + </div> + {% endif %} + <h3 class="highlight">Publications</h3> <table class="table"> {% for pub in object.publications.all %} @@ -26,3 +54,7 @@ </table> {% endblock content %} + +{% block footer_script %} + {{ add_manager_form.media }} +{% endblock footer_script %} diff --git a/affiliates/urls.py b/affiliates/urls.py index 91ce17930..7edcc3664 100644 --- a/affiliates/urls.py +++ b/affiliates/urls.py @@ -22,6 +22,16 @@ urlpatterns = [ views.AffiliateJournalDetailView.as_view(), name='journal_detail' ), + path( # /affiliations/journals/<slug>/add_manager + 'journals/<slug:slug>/add_manager', + views.affiliatejournal_add_manager, + name='journal_add_manager' + ), + path( # /affiliations/journals/<slug>/remove_manager + 'journals/<slug:slug>/remove_manager/<int:user_id>', + views.affiliatejournal_remove_manager, + name='journal_remove_manager' + ), path( # /affiliates/publications/<doi:doi> 'publications/<doi:doi>', views.AffiliatePublicationDetailView.as_view(), diff --git a/affiliates/views.py b/affiliates/views.py index 0a6661eb4..d6cf6df23 100644 --- a/affiliates/views.py +++ b/affiliates/views.py @@ -2,11 +2,17 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" __license__ = "AGPL v3" -from django.shortcuts import render +from django.contrib.auth.models import User +from django.shortcuts import get_object_or_404, render, redirect +from django.urls import reverse from django.views.generic.detail import DetailView from django.views.generic.list import ListView +from guardian.decorators import permission_required_or_403 +from guardian.shortcuts import assign_perm, remove_perm, get_users_with_perms + from .models import AffiliateJournal, AffiliatePublication +from .forms import AddAffiliateJournalManagerForm class AffiliateJournalListView(ListView): @@ -16,6 +22,36 @@ class AffiliateJournalListView(ListView): class AffiliateJournalDetailView(DetailView): model = AffiliateJournal + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + context['journal_managers'] = get_users_with_perms( + self.object, + with_superusers=False + ) + context['add_manager_form'] = AddAffiliateJournalManagerForm() + return context + + +@permission_required_or_403('affiliates.change_affiliatejournal', + (AffiliateJournal, 'slug', 'slug')) +def affiliatejournal_add_manager(request, slug): + journal = get_object_or_404(AffiliateJournal, slug=slug) + form = AddAffiliateJournalManagerForm(request.POST or None) + if form.is_valid(): + assign_perm('manage_journal_content', + form.cleaned_data['user'], journal) + return redirect(reverse('affiliates:journal_detail', + kwargs={'slug': slug})) + +@permission_required_or_403('affiliates.change_affiliatejournal', + (AffiliateJournal, 'slug', 'slug')) +def affiliatejournal_remove_manager(request, slug, user_id): + journal = get_object_or_404(AffiliateJournal, slug=slug) + user = get_object_or_404(User, pk=user_id) + remove_perm('manage_journal_content', user, journal) + return redirect(reverse('affiliates:journal_detail', + kwargs={'slug': slug})) + class AffiliatePublicationDetailView(DetailView): model = AffiliatePublication -- GitLab