diff --git a/affiliates/forms.py b/affiliates/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..0839871eaf9a7d3514a8d5e48f5b8d34c03c61ca --- /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 0000000000000000000000000000000000000000..c8752a1d9f09f50e06c9101704a4d140fbb72c6a --- /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 989f257e6364c9d1757fc7df5dc78c508371ce82..aaf90d242c54d7dea790ec4dd9ab6a5854dfb820 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 809358b39d7f84aedc784ae983e422e02bc47c32..5b0b65826d6e568ff9aec6f7a5e23e923753b08c 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 91ce179305ffcc40f5a5c21813183a36bd78c854..7edcc366444fe40df9438cf49864add5bc534c92 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 0a6661eb4f2e0f761d78db2fb0b161bc7d3d0ebb..d6cf6df238980ddb965471751e7e0e84fe65a827 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