diff --git a/invitations/forms.py b/invitations/forms.py index 45e5fa3b5b9360981891ac511315f544f6115708..9edf2f0fdb460ce221cad63c67111d1347a01fbb 100644 --- a/invitations/forms.py +++ b/invitations/forms.py @@ -17,14 +17,6 @@ class AcceptRequestMixin: super().__init__(*args, **kwargs) -class RegistrationInvitationFilterForm(forms.Form): - last_name = forms.CharField() - - def search(self, qs): - last_name = self.cleaned_data.get('last_name') - return qs.filter(last_name__icontains=last_name) - - class SuggestionSearchForm(forms.Form): last_name = forms.CharField() diff --git a/invitations/migrations/0011_auto_20180220_1139.py b/invitations/migrations/0011_auto_20180220_1139.py index e4223f3b81d0034af99098b5ab4a0565204e2499..3c09869ae12640b8729f6e7df0fab8399c976601 100644 --- a/invitations/migrations/0011_auto_20180220_1139.py +++ b/invitations/migrations/0011_auto_20180220_1139.py @@ -1,7 +1,12 @@ # -*- coding: utf-8 -*- # Generated by Django 1.11.4 on 2018-02-20 10:39 from __future__ import unicode_literals +import datetime +import hashlib +import random +import string +from django.utils import timezone from django.db import migrations # Hack @@ -9,7 +14,7 @@ from django.contrib.auth import get_user_model def transfer_old_invitations_to_new_tables(apps, schema_editor): - OldDraftInvitation = apps.get_model('scipost', 'RegistrationInvitation') + OldDraftInvitation = apps.get_model('scipost', 'DraftInvitation') OldRegistrationInvitation = apps.get_model('scipost', 'RegistrationInvitation') OldCitationNotification = apps.get_model('scipost', 'CitationNotification') NewRegistrationInvitation = apps.get_model('invitations', 'RegistrationInvitation') @@ -59,7 +64,7 @@ def transfer_old_invitations_to_new_tables(apps, schema_editor): created=new_inv.created, modified=new_inv.modified, submission_id=invitation.cited_in_submission.id, - date_sent=invitation.date_sent_first, + date_sent=invitation.date_last_reminded, processed=(new_inv.status in ['declined', 'register', 'sent']), ) if invitation.cited_in_publication: @@ -69,12 +74,12 @@ def transfer_old_invitations_to_new_tables(apps, schema_editor): created=new_inv.created, modified=new_inv.modified, publication_id=invitation.cited_in_publication.id, - date_sent=invitation.date_sent_first, + date_sent=invitation.date_last_reminded, processed=(new_inv.status in ['declined', 'register', 'sent']), ) # Draft Invitations - for invitation in OldDraftInvitation.objects.processed(processed=False): + for invitation in OldDraftInvitation.objects.filter(processed=False): new_inv = NewRegistrationInvitation( title=invitation.title, first_name=invitation.first_name, @@ -92,6 +97,15 @@ def transfer_old_invitations_to_new_tables(apps, schema_editor): ) if new_inv.invitation_type in ['ci', 'cp']: new_inv.invitation_type = 'C' + + # Generate keys, custom methods are not loaded here + salt = '' + for i in range(5): + salt += random.choice(string.ascii_letters) + salt = salt.encode('utf8') + invitationsalt = new_inv.last_name.encode('utf8') + new_inv.invitation_key = hashlib.sha1(salt + invitationsalt).hexdigest() + new_inv.key_expires = timezone.now() + datetime.timedelta(days=365) new_inv.save() if invitation.cited_in_submission: diff --git a/invitations/templates/invitations/registrationinvitation_list.html b/invitations/templates/invitations/registrationinvitation_list.html index 9ef7afeeaa17c0fda2f5ba2d806ae1866e807c97..3dbff91fc077dcb0ce0bc5a5e7368d0f9cdefb55 100644 --- a/invitations/templates/invitations/registrationinvitation_list.html +++ b/invitations/templates/invitations/registrationinvitation_list.html @@ -24,6 +24,11 @@ <li><a href="{% url 'invitations:cleanup' %}">Perform a cleanup</a></li> <li><a href="{% url 'invitations:citation_notification_list' %}">List unprocessed Citation Notifications</a></li> {% endif %} + {% if perms.scipost.can_invite_fellows %} + <li><a href="{% url 'invitations:list_fellows' %}">List Fellow Invitations</a></li> + {% endif %} + + <li><a href="{% url 'invitations:list_sent' %}">Show all Invitations pending response</a></li> </ul> </div> <div class="col-md-6 text-md-right"> @@ -42,13 +47,11 @@ <div class="col-12"> <h2 class="highlight">Registration Invitations</h2> </div> - <div class="col-md-6"> - <form method="get"> - {{ search_form|bootstrap }} - <input class="btn btn-primary" type="submit" value="Filter"> - <a href="{% url 'invitations:list' %}" class="btn btn-link">Reset filter</a> - </form> - </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} <div class="col-12"> <br> {% include 'partials/invitations/registrationinvitation_table.html' with invitations=object_list %} @@ -56,6 +59,11 @@ <a href="{% url 'invitations:list' %}" class="btn btn-link">Reset filter</a> {% endif %} </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} </div> {% endblock %} diff --git a/invitations/templates/invitations/registrationinvitation_list_fellows.html b/invitations/templates/invitations/registrationinvitation_list_fellows.html new file mode 100644 index 0000000000000000000000000000000000000000..b2f4552e491c73a7385375529f1864d9007b6602 --- /dev/null +++ b/invitations/templates/invitations/registrationinvitation_list_fellows.html @@ -0,0 +1,39 @@ +{% extends 'scipost/_personal_page_base.html' %} + +{% load bootstrap %} + +{% block pagetitle %}: Registration Invitations{% endblock pagetitle %} + +{% block breadcrumb_items %} + {{block.super}} + <a href="{% url 'invitations:list' %}" class="breadcrumb-item">Registration Invitations</a> + <span class="breadcrumb-item">Fellows</span> +{% endblock %} + +{% block content %} + +<h1 class="highlight">Registration Invitations Fellows</h1> + + +<div class="row"> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} + <div class="col-12"> + <br> + + {% include 'partials/invitations/registrationinvitation_table.html' with invitations=object_list %} + {% if search_form.is_bound %} + <a href="{% url 'invitations:list_sent' %}" class="btn btn-link">Reset filter</a> + {% endif %} + </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} +</div> + +{% endblock %} diff --git a/invitations/templates/invitations/registrationinvitation_list_sent.html b/invitations/templates/invitations/registrationinvitation_list_sent.html new file mode 100644 index 0000000000000000000000000000000000000000..36756401e5da6bdb8bb6f259f02283c105c3e881 --- /dev/null +++ b/invitations/templates/invitations/registrationinvitation_list_sent.html @@ -0,0 +1,39 @@ +{% extends 'scipost/_personal_page_base.html' %} + +{% load bootstrap %} + +{% block pagetitle %}: Registration Invitations{% endblock pagetitle %} + +{% block breadcrumb_items %} + {{block.super}} + <a href="{% url 'invitations:list' %}" class="breadcrumb-item">Registration Invitations</a> + <span class="breadcrumb-item">Sent</span> +{% endblock %} + +{% block content %} + +<h1 class="highlight">Sent Registration Invitations</h1> + + +<div class="row"> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} + <div class="col-12"> + <br> + + {% include 'partials/invitations/registrationinvitation_table.html' with invitations=object_list %} + {% if search_form.is_bound %} + <a href="{% url 'invitations:list_sent' %}" class="btn btn-link">Reset filter</a> + {% endif %} + </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} +</div> + +{% endblock %} diff --git a/invitations/urls.py b/invitations/urls.py index d53b7ea3ef19fb78c221549ca4d81d78fedc8f33..039e3de0d3f4752fa2400686e8b3f0edaf3bb036 100644 --- a/invitations/urls.py +++ b/invitations/urls.py @@ -4,6 +4,8 @@ from . import views urlpatterns = [ url(r'^$', views.RegistrationInvitationsView.as_view(), name='list'), + url(r'^sent$', views.RegistrationInvitationsSentView.as_view(), name='list_sent'), + url(r'^fellows$', views.RegistrationInvitationsFellowView.as_view(), name='list_fellows'), url(r'^new$', views.create_registration_invitation_or_citation, name='new'), url(r'^(?P<pk>[0-9]+)$', views.RegistrationInvitationsUpdateView.as_view(), name='update'), url(r'^(?P<pk>[0-9]+)/add_citation$', views.RegistrationInvitationsAddCitationView.as_view(), diff --git a/invitations/views.py b/invitations/views.py index 05d613180a27874e70cf58c985a38020e0d20a9c..9f2e647dd3e29d0dd2b26ff43f55c5b3435fc582 100644 --- a/invitations/views.py +++ b/invitations/views.py @@ -8,36 +8,38 @@ from django.views.generic.edit import UpdateView, DeleteView from .forms import RegistrationInvitationForm, RegistrationInvitationReminderForm,\ RegistrationInvitationMarkForm, RegistrationInvitationMapToContributorForm,\ - CitationNotificationForm, SuggestionSearchForm, RegistrationInvitationFilterForm,\ + CitationNotificationForm, SuggestionSearchForm,\ CitationNotificationProcessForm, RegistrationInvitationAddCitationForm from .mixins import RequestArgumentMixin, PermissionsMixin, SaveAndSendFormMixin, SendMailFormMixin from .models import RegistrationInvitation, CitationNotification from scipost.models import Contributor +from scipost.mixins import PaginationMixin from mails.mixins import MailEditorMixin -class RegistrationInvitationsView(PermissionsMixin, ListView): +class RegistrationInvitationsView(PaginationMixin, PermissionsMixin, ListView): permission_required = 'scipost.can_create_registration_invitations' - queryset = RegistrationInvitation.objects.no_response() + queryset = RegistrationInvitation.objects.drafts().not_for_fellows() + paginate_by = 10 def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['count_in_draft'] = RegistrationInvitation.objects.drafts().count() context['count_pending'] = RegistrationInvitation.objects.sent().count() - search_form = RegistrationInvitationFilterForm(self.request.GET or None) - if search_form.is_valid(): - context['object_list'] = search_form.search(context['object_list']) - context['object_list'] = context['object_list'].order_by( - 'status', 'date_sent_last', 'last_name') - context['search_form'] = search_form return context - def get_queryset(self, *args, **kwargs): - qs = super().get_queryset(*args, **kwargs) - if not self.request.user.has_perm('scipost.can_invite_fellows'): - qs = qs.not_for_fellows() - return qs + +class RegistrationInvitationsSentView(RegistrationInvitationsView): + permission_required = 'scipost.can_create_registration_invitations' + queryset = RegistrationInvitation.objects.sent().not_for_fellows() + template_name = 'invitations/registrationinvitation_list_sent.html' + + +class RegistrationInvitationsFellowView(RegistrationInvitationsView): + permission_required = 'scipost.can_invite_fellows' + queryset = RegistrationInvitation.objects.for_fellows() + template_name = 'invitations/registrationinvitation_list_fellows.html' class CitationNotificationsView(PermissionsMixin, ListView): diff --git a/scipost/mixins.py b/scipost/mixins.py index 49dec74f4c44887c0667fbfb9caebf1128e4739b..0cdb24844cca643934797c665b3357a01caabf82 100644 --- a/scipost/mixins.py +++ b/scipost/mixins.py @@ -1,7 +1,7 @@ from .paginator import SciPostPaginator -class PaginationMixin(object): +class PaginationMixin: """ Mixin for generic class-based views (e.g. django.views.generic.ListView) """ diff --git a/scipost/templatetags/scipost_extras.py b/scipost/templatetags/scipost_extras.py index 4e9f47e186c03bdb18ae71c828c29efa40108073..25eca4f9f7521cea8bfaa8ac54bc410521651c49 100644 --- a/scipost/templatetags/scipost_extras.py +++ b/scipost/templatetags/scipost_extras.py @@ -38,7 +38,8 @@ def is_in_group(user, group_name): @register.filter(name='associated_contributors') def associated_contributors(draft): - return Contributor.objects.filter(user__last_name__icontains=draft.last_name) + return Contributor.objects.filter( + user__last_name__icontains=draft.last_name).order_by('user__last_name') def is_modulo(counter, total, modulo):