From 73179b8e68c6912b60adc58b00ecc887e4b0153f Mon Sep 17 00:00:00 2001 From: Jorran de Wit <jorrandewit@outlook.com> Date: Tue, 15 Aug 2017 16:11:12 +0200 Subject: [PATCH] Remove HTML from Contributor model --- config.scss | 0 scipost/managers.py | 9 +++ scipost/models.py | 68 +++---------------- .../contributor_assignments_as_td.html | 14 ++++ .../scipost/Fellow_activity_overview.html | 25 +++++-- scipost/templates/scipost/personal_page.html | 62 +++++++++-------- scipost/urls.py | 6 +- scipost/views.py | 37 +++++----- submissions/managers.py | 20 +++++- submissions/models.py | 8 ++- .../admin/editorial_admin_summary.html | 2 +- .../submissions/_submission_card_in_pool.html | 4 +- .../submissions/assign_submission.html | 4 +- submissions/views.py | 4 +- 14 files changed, 138 insertions(+), 125 deletions(-) create mode 100644 config.scss create mode 100644 scipost/templates/partials/scipost/contributor_assignments_as_td.html diff --git a/config.scss b/config.scss new file mode 100644 index 000000000..e69de29bb diff --git a/scipost/managers.py b/scipost/managers.py index 1a4a401fd..d108e255b 100644 --- a/scipost/managers.py +++ b/scipost/managers.py @@ -25,6 +25,9 @@ class ContributorManager(models.Manager): def awaiting_validation(self): return self.filter(user__is_active=False, status=CONTRIBUTOR_NEWLY_REGISTERED) + def fellows(self): + return self.filter(user__groups__name='Editorial College') + class RegistrationInvitationManager(models.Manager): def pending_invited_fellows(self): @@ -34,3 +37,9 @@ class RegistrationInvitationManager(models.Manager): def declined_invited_fellows(self): return self.filter(invitation_type=INVITATION_EDITORIAL_FELLOW, responded=False, declined=True) + + +class UnavailabilityPeriodManager(models.Manager): + def today(self): + today = datetime.date.today() + return self.filter(start__lte=today, end__gte=today) diff --git a/scipost/models.py b/scipost/models.py index a1e542d81..7d05b6a02 100644 --- a/scipost/models.py +++ b/scipost/models.py @@ -9,7 +9,6 @@ from django.contrib.postgres.fields import ArrayField from django.db import models from django.template import Template, Context from django.utils import timezone -from django.urls import reverse from django_countries.fields import CountryField @@ -20,7 +19,8 @@ from .constants import SCIPOST_DISCIPLINES, SCIPOST_SUBJECT_AREAS,\ INVITATION_CONTRIBUTOR, INVITATION_FORMAL,\ AUTHORSHIP_CLAIM_PENDING, AUTHORSHIP_CLAIM_STATUS from .fields import ChoiceArrayField -from .managers import FellowManager, ContributorManager, RegistrationInvitationManager +from .managers import FellowManager, ContributorManager, RegistrationInvitationManager,\ + UnavailabilityPeriodManager def get_sentinel_user(): @@ -73,9 +73,14 @@ class Contributor(models.Model): def get_absolute_url(self): return reverse('scipost:contributor_info', args=(self.id,)) + @property def get_formal_display(self): return '%s %s %s' % (self.get_title_display(), self.user.first_name, self.user.last_name) + @property + def is_currently_available(self): + return not self.unavailability_periods.today().exists() + def is_SP_Admin(self): return self.user.groups.filter(name='SciPost Administrators').exists() @@ -85,15 +90,6 @@ class Contributor(models.Model): def is_VE(self): return self.user.groups.filter(name='Vetting Editors').exists() - def is_currently_available(self): - unav_periods = UnavailabilityPeriod.objects.filter(contributor=self) - - today = datetime.date.today() - for unav in unav_periods: - if unav.start < today and unav.end > today: - return False - return True - def get_activation_key(self): if not self._activation_key: self.generate_key() @@ -117,57 +113,15 @@ class Contributor(models.Model): return ', '.join([subject_areas_dict[exp].lower() for exp in self.expertises]) return '' - def assignments_summary_as_td(self): - assignments = self.editorialassignment_set.all() - nr_ongoing = assignments.filter(accepted=True, completed=False).count() - nr_last_12mo = assignments.filter( - date_created__gt=timezone.now() - timezone.timedelta(days=365)).count() - nr_accepted = assignments.filter(accepted=True).count() - nr_accepted_last_12mo = assignments.filter( - accepted=True, date_created__gt=timezone.now() - timezone.timedelta(days=365)).count() - nr_refused = assignments.filter(accepted=False).count() - nr_refused_last_12mo = assignments.filter( - accepted=False, date_created__gt=timezone.now() - timezone.timedelta(days=365)).count() - nr_ignored = assignments.filter(accepted=None).count() - nr_ignored_last_12mo = assignments.filter( - accepted=None, date_created__gt=timezone.now() - timezone.timedelta(days=365)).count() - nr_completed = assignments.filter(completed=True).count() - nr_completed_last_12mo = assignments.filter( - completed=True, date_created__gt=timezone.now() - timezone.timedelta(days=365)).count() - - context = Context({ - 'nr_ongoing': nr_ongoing, - 'nr_total': assignments.count(), - 'nr_last_12mo': nr_last_12mo, - 'nr_accepted': nr_accepted, - 'nr_accepted_last_12mo': nr_accepted_last_12mo, - 'nr_refused': nr_refused, - 'nr_refused_last_12mo': nr_refused_last_12mo, - 'nr_ignored': nr_ignored, - 'nr_ignored_last_12mo': nr_ignored_last_12mo, - 'nr_completed': nr_completed, - 'nr_completed_last_12mo': nr_completed_last_12mo, - }) - output = '<td>' - if self.expertises: - for expertise in self.expertises: - output += subject_areas_dict[expertise] + '<br/>' - output += ('</td>' - '<td>{{ nr_ongoing }}</td>' - '<td>{{ nr_last_12mo }} / {{ nr_total }}</td>' - '<td>{{ nr_accepted_last_12mo }} / {{ nr_accepted }}</td>' - '<td>{{ nr_refused_last_12mo }} / {{ nr_refused }}</td>' - '<td>{{ nr_ignored_last_12mo }} / {{ nr_ignored }}</td>' - '<td>{{ nr_completed_last_12mo }} / {{ nr_completed }}</td>\n') - template = Template(output) - return template.render(context) - class UnavailabilityPeriod(models.Model): - contributor = models.ForeignKey('scipost.Contributor', on_delete=models.CASCADE) + contributor = models.ForeignKey('scipost.Contributor', on_delete=models.CASCADE, + related_name='unavailability_periods') start = models.DateField() end = models.DateField() + objects = UnavailabilityPeriodManager() + class Meta: ordering = ['-start'] diff --git a/scipost/templates/partials/scipost/contributor_assignments_as_td.html b/scipost/templates/partials/scipost/contributor_assignments_as_td.html new file mode 100644 index 000000000..4f6d8b211 --- /dev/null +++ b/scipost/templates/partials/scipost/contributor_assignments_as_td.html @@ -0,0 +1,14 @@ +{% load scipost_extras %} + +<td> + {% for expertise in contributor.expertises %} + {{expertise|get_specialization_display}}<br> + {% endfor %} +</td> + +<td>{{contributor.editorial_assignments.ongoing.count}}</td> +<td>{{contributor.editorial_assignments.last_year.count}} / {{contributor.editorial_assignments.count}}</td> +<td>{{contributor.editorial_assignments.last_year.accepted.count}} / {{contributor.editorial_assignments.accepted.count}}</td> +<td>{{contributor.editorial_assignments.last_year.refused.count}} / {{contributor.editorial_assignments.refused.count}}</td> +<td>{{contributor.editorial_assignments.last_year.ignored.count}} / {{contributor.editorial_assignments.ignored.count}}</td> +<td>{{contributor.editorial_assignments.last_year.completed.count}} / {{contributor.editorial_assignments.completed.count}}</td> diff --git a/scipost/templates/scipost/Fellow_activity_overview.html b/scipost/templates/scipost/Fellow_activity_overview.html index 3e2bacaa8..e0515b486 100644 --- a/scipost/templates/scipost/Fellow_activity_overview.html +++ b/scipost/templates/scipost/Fellow_activity_overview.html @@ -1,10 +1,15 @@ -{% extends 'scipost/base.html' %} +{% extends 'scipost/_personal_page_base.html' %} {% block pagetitle %}: Overview{% endblock pagetitle %} {% load scipost_extras %} {% load submissions_extras %} +{% block breadcrumb_items %} + {{block.super}} + <span class="breadcrumb-item">Overview of Fellow's activities</span> +{% endblock %} + {% block content %} <div class="row"> @@ -29,10 +34,12 @@ </thead> <tbody> {% for fellow in fellows %} - <tr> - <td><a href="{% url 'scipost:Fellow_activity_overview' Fellow_id=fellow.id %}">{{ fellow.user.last_name }}, {{ fellow.user.first_name }}</a></td> - {{ fellow.assignments_summary_as_td }} - </tr> + <tr> + <td> + <a href="{% url 'scipost:Fellow_activity_overview' %}?fellow={{fellow.id}}">{{ fellow.user.last_name }}, {{ fellow.user.first_name }}</a> + </td> + {% include 'partials/scipost/contributor_assignments_as_td.html' with contributor=fellow %} + </tr> {% endfor %} </tbody> </table> @@ -56,12 +63,14 @@ <li class="list-group-item"> {% include 'submissions/_submission_card_contributor_content.html' with submission=assignment.submission %} </li> + {% empty %} + <li class="list-group-item">No completed assignments</li> {% endfor %} </ul> </div> - <div class="col-12"> - <h3>Completed:</h3> + <div class="col-12 mt-4"> + <h3>Completed</h3> </div> <div class="col-12"> @@ -70,6 +79,8 @@ <li class="list-group-item"> {% include 'submissions/_submission_card_contributor_content.html' with submission=assignment.submission %} </li> + {% empty %} + <li class="list-group-item">No completed assignments</li> {% endfor %} </ul> </div> diff --git a/scipost/templates/scipost/personal_page.html b/scipost/templates/scipost/personal_page.html index 56cafa251..c7bd7000a 100644 --- a/scipost/templates/scipost/personal_page.html +++ b/scipost/templates/scipost/personal_page.html @@ -103,36 +103,42 @@ {% endif %} </div> <div class="col-md-6"> + {% if not request.user.contributor.is_currently_available %} + <h3 class="text-warning">You are currently unavailable</h3> + <p>Check your availability underneath if this should not be the case.</p> + <hr> + {% endif %} + {% if 'SciPost Administrators' in user_groups %} - <h3>You are a SciPost Administrator.</h3> + <h3>You are a SciPost Administrator.</h3> {% endif %} {% if 'Editorial Administrators' in user_groups %} - <h3>You are a SciPost Editorial Administrator.</h3> + <h3>You are a SciPost Editorial Administrator.</h3> {% endif %} {% if 'Advisory Board' in user_groups %} - <h3>You are a member of the Advisory Board.</h3> + <h3>You are a member of the Advisory Board.</h3> {% endif %} {% if 'Editorial College' in user_groups %} - <h3>You are a member of the Editorial College.</h3> - {% endif %} - {% if 'Vetting Editors' in user_groups %} - <h3>You are a SciPost Vetting Editor.</h3> - {% endif %} - {% if 'Registered Contributors' in user_groups %} - <h3>You are a Registered Contributor.</h3> - {% endif %} - {% if 'Testers' in user_groups %} - <h3>You are a SciPost Tester.</h3> - {% endif %} - {% if 'Ambassadors' in user_groups %} - <h3>You are a SciPost Ambassador.</h3> - {% endif %} - {% if 'Junior Ambassadors' in user_groups %} - <h3>You are a SciPost Junior Ambassador.</h3> - {% endif %} - {% if 'Production Officers' in user_groups %} - <h3>You are a SciPost Production Officer.</h3> - {% endif %} + <h3>You are a member of the Editorial College.</h3> + {% endif %} + {% if 'Vetting Editors' in user_groups %} + <h3>You are a SciPost Vetting Editor.</h3> + {% endif %} + {% if 'Registered Contributors' in user_groups %} + <h3>You are a Registered Contributor.</h3> + {% endif %} + {% if 'Testers' in user_groups %} + <h3>You are a SciPost Tester.</h3> + {% endif %} + {% if 'Ambassadors' in user_groups %} + <h3>You are a SciPost Ambassador.</h3> + {% endif %} + {% if 'Junior Ambassadors' in user_groups %} + <h3>You are a SciPost Junior Ambassador.</h3> + {% endif %} + {% if 'Production Officers' in user_groups %} + <h3>You are a SciPost Production Officer.</h3> + {% endif %} <h3 class="mt-3">Update your personal data or password</h3> @@ -145,12 +151,8 @@ <hr> <div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h2 class="card-title mb-0">Your Availability</h2> - </div> - </div> + <div class="col"> + <h2 class="highlight">Your Availability</h2> </div> </div> <div class="row justify-content-center"> @@ -166,7 +168,7 @@ <div class="col-md-4 ml-md-5"> {% if unavailabilities %} <h3>Your unavailability periods in our records</h3> - <p class="text-muted">(YYYY-DD-MM)</p> + <p class="text-muted">(YYYY-MM-DD)</p> <table class="table"> <tr> <th>Start</th> diff --git a/scipost/urls.py b/scipost/urls.py index 8eaf7b40e..eb36c827b 100644 --- a/scipost/urls.py +++ b/scipost/urls.py @@ -168,11 +168,7 @@ urlpatterns = [ # Editorial College # ##################### url(r'^EdCol_by-laws$', views.EdCol_bylaws, name='EdCol_by-laws'), - url(r'^Fellow_activity_overview/(?P<Fellow_id>[0-9]+)$', - views.Fellow_activity_overview, - name='Fellow_activity_overview'), - url(r'^Fellow_activity_overview$', - views.Fellow_activity_overview, + url(r'^Fellow_activity_overview$', views.Fellow_activity_overview, name='Fellow_activity_overview'), diff --git a/scipost/views.py b/scipost/views.py index 22361d5ad..5d287072b 100644 --- a/scipost/views.py +++ b/scipost/views.py @@ -1299,22 +1299,27 @@ def EdCol_bylaws(request): @permission_required('scipost.can_view_pool', return_403=True) -def Fellow_activity_overview(request, Fellow_id=None): - fellows = Contributor.objects.filter( - user__groups__name='Editorial College').order_by('user__last_name') - context = {'fellows': fellows} - if Fellow_id: - fellow = get_object_or_404(Contributor, pk=Fellow_id) - context['fellow'] = fellow - - assignments_ongoing = (EditorialAssignment.objects.get_for_user_in_pool(request.user) - .filter(accepted=True, completed=False, to=fellow) - .order_by('-date_created')) - context['assignments_ongoing'] = assignments_ongoing - - assignments_completed = (EditorialAssignment.objects.get_for_user_in_pool(request.user) - .filter(completed=True, to=fellow).order_by('-date_created')) - context['assignments_completed'] = assignments_completed +def Fellow_activity_overview(request): + fellows = (Contributor.objects.fellows() + .prefetch_related('editorial_assignments') + .order_by('user__last_name')) + context = { + 'fellows': fellows + } + + if request.GET.get('fellow'): + try: + fellow = fellows.get(pk=request.GET['fellow']) + context['fellow'] = fellow + + context['assignments_ongoing'] = (fellow.editorial_assignments + .ongoing() + .get_for_user_in_pool(request.user)) + context['assignments_completed'] = (fellow.editorial_assignments + .completed() + .get_for_user_in_pool(request.user)) + except Contributor.DoesNotExist: + pass return render(request, 'scipost/Fellow_activity_overview.html', context) diff --git a/submissions/managers.py b/submissions/managers.py index 3465c643a..e4b5b5f2a 100644 --- a/submissions/managers.py +++ b/submissions/managers.py @@ -144,12 +144,30 @@ class SubmissionEventQuerySet(models.QuerySet): return self.filter(created__gte=timezone.now() - datetime.timedelta(hours=hours)) -class EditorialAssignmentManager(models.Manager): +class EditorialAssignmentQuerySet(models.QuerySet): def get_for_user_in_pool(self, user): return self.exclude(submission__authors=user.contributor)\ .exclude(Q(submission__author_list__icontains=user.last_name), ~Q(submission__authors_false_claims=user.contributor)) + def last_year(self): + return self.filter(date_created__gt=timezone.now() - timezone.timedelta(days=365)) + + def accepted(self): + return self.filter(accepted=True) + + def refused(self): + return self.filter(accepted=False) + + def ignored(self): + return self.filter(accepted=None) + + def completed(self): + return self.filter(completed=True) + + def ongoing(self): + return self.filter(completed=False).accepted() + class EICRecommendationManager(models.Manager): def get_for_user_in_pool(self, user): diff --git a/submissions/models.py b/submissions/models.py index 4c69c9e70..f5a03da1d 100644 --- a/submissions/models.py +++ b/submissions/models.py @@ -15,7 +15,7 @@ from .constants import ASSIGNMENT_REFUSAL_REASONS, ASSIGNMENT_NULLBOOL,\ REPORT_STATUSES, STATUS_UNVETTED, SUBMISSION_EIC_RECOMMENDATION_REQUIRED,\ SUBMISSION_CYCLES, CYCLE_DEFAULT, CYCLE_SHORT, CYCLE_DIRECT_REC,\ EVENT_GENERAL, EVENT_TYPES, EVENT_FOR_AUTHOR, EVENT_FOR_EIC -from .managers import SubmissionQuerySet, EditorialAssignmentManager, EICRecommendationManager,\ +from .managers import SubmissionQuerySet, EditorialAssignmentQuerySet, EICRecommendationManager,\ ReportQuerySet, SubmissionEventQuerySet, RefereeInvitationQuerySet from .utils import ShortSubmissionCycle, DirectRecommendationSubmissionCycle,\ GeneralSubmissionCycle @@ -264,7 +264,11 @@ class EditorialAssignment(SubmissionRelatedObjectMixin, models.Model): date_created = models.DateTimeField(default=timezone.now) date_answered = models.DateTimeField(blank=True, null=True) - objects = EditorialAssignmentManager() + objects = EditorialAssignmentQuerySet.as_manager() + + class Meta: + default_related_name = 'editorial_assignments' + ordering = ['-date_created'] def __str__(self): return (self.to.user.first_name + ' ' + self.to.user.last_name + ' to become EIC of ' + diff --git a/submissions/templates/partials/submissions/admin/editorial_admin_summary.html b/submissions/templates/partials/submissions/admin/editorial_admin_summary.html index 60f10bf1a..5d8c75447 100644 --- a/submissions/templates/partials/submissions/admin/editorial_admin_summary.html +++ b/submissions/templates/partials/submissions/admin/editorial_admin_summary.html @@ -96,7 +96,7 @@ {% if not submission.editor_in_charge %} <li>EIC Assignment requests:</li> <ul> - {% for assignment in submission.editorialassignment_set.all %} + {% for assignment in submission.editorial_assignments.all %} {% include 'submissions/_assignment_info.html' with assignment=assignment %} {% empty %} <li>None found. <a href="{% url 'submissions:assign_submission' submission.arxiv_identifier_w_vn_nr %}">Send a first assignment request</a></li> diff --git a/submissions/templates/submissions/_submission_card_in_pool.html b/submissions/templates/submissions/_submission_card_in_pool.html index 05eb57d34..5425c1195 100644 --- a/submissions/templates/submissions/_submission_card_in_pool.html +++ b/submissions/templates/submissions/_submission_card_in_pool.html @@ -28,10 +28,10 @@ {% endif %} {% if perms.scipost.can_assign_submissions %} - {% if submission.editorialassignment_set.all %} + {% if submission.editorial_assignments.exists %} <h4>EIC Assignment requests:</h4> <ul> - {% for assignment in submission.editorialassignment_set.all %} + {% for assignment in submission.editorial_assignments.all %} {% include 'submissions/_assignment_info.html' with assignment=assignment %} {% endfor %} </ul> diff --git a/submissions/templates/submissions/assign_submission.html b/submissions/templates/submissions/assign_submission.html index 92020ea32..ce677a88f 100644 --- a/submissions/templates/submissions/assign_submission.html +++ b/submissions/templates/submissions/assign_submission.html @@ -39,11 +39,11 @@ <div class="row"> <div class="col-12"> - {% if submission_to_assign.editorialassignment_set.all %} + {% if submission_to_assign.editorial_assignments.exists %} <h4>EIC Assignment requests already sent:</h4> <h3>If more than 5 Fellows have declined an assignment for a red-marked reason, the Submission should be rejected.</h3> <ul> - {% for assignment in sub.editorialassignment_set.all %} + {% for assignment in sub.editorial_assignments.all %} {% include 'submissions/_assignment_info.html' with assignment=assignment %} {% endfor %} </ul> diff --git a/submissions/views.py b/submissions/views.py index 3294cb044..c4adc1fbd 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -439,7 +439,7 @@ def assign_submission_ack(request, arxiv_identifier_w_vn_nr): if form.is_valid(): suggested_editor_in_charge = form.cleaned_data['editor_in_charge'] # TODO: check for possible co-authorships, disqualifying this suggested EIC - if not suggested_editor_in_charge.is_currently_available(): + if not suggested_editor_in_charge.is_currently_available: errormessage = ('This Fellow is marked as currently unavailable. ' 'Please go back and select another one.') return render(request, 'scipost/error.html', {'errormessage': errormessage}) @@ -774,7 +774,7 @@ def send_refereeing_invitation(request, arxiv_identifier_w_vn_nr, contributor_id submission = get_object_or_404(Submission.objects.get_pool(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) contributor = get_object_or_404(Contributor, pk=contributor_id) - if not contributor.is_currently_available(): + if not contributor.is_currently_available: errormessage = ('This Contributor is marked as currently unavailable. ' 'Please go back and select another referee.') return render(request, 'scipost/error.html', {'errormessage': errormessage}) -- GitLab