From 45a84ad981ccfe098a91965da45644f883c6fd63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20Caux?= <git@jscaux.org> Date: Sun, 27 Nov 2022 14:55:17 +0100 Subject: [PATCH] Polish pool tooling --- scipost_django/submissions/forms.py | 72 ++++++++++++------- .../submissions/managers/submission.py | 14 ++-- scipost_django/submissions/views.py | 39 +++++----- 3 files changed, 76 insertions(+), 49 deletions(-) diff --git a/scipost_django/submissions/forms.py b/scipost_django/submissions/forms.py index 70df4c571..b684fc54e 100644 --- a/scipost_django/submissions/forms.py +++ b/scipost_django/submissions/forms.py @@ -12,7 +12,7 @@ from django.forms.formsets import ORDERING_FIELD_NAME from django.utils import timezone from crispy_forms.helper import FormHelper -from crispy_forms.layout import Layout, Div, Fieldset, ButtonHolder, Submit +from crispy_forms.layout import Layout, Div, Field, Fieldset, ButtonHolder, Submit from crispy_forms.bootstrap import InlineRadios from crispy_bootstrap5.bootstrap5 import FloatingField @@ -232,7 +232,7 @@ class SubmissionPoolSearchForm(forms.Form): ( "Revision requested", ( - ("revision_requested", "Minor or major revision requested"), + ("revision_requested", "Minor or major revision requested, awaiting resubmission"), ), ), ( @@ -264,11 +264,22 @@ class SubmissionPoolSearchForm(forms.Form): editor_in_charge = forms.ModelChoiceField( queryset=Fellowship.objects.active(), required=False ) + versions = forms.ChoiceField( + widget=forms.RadioSelect, + choices=( + ("latest", "Latest submitted only"), + ("any", "All versions"), + ), + initial="latest", + ) search_set = forms.ChoiceField( widget=forms.RadioSelect, choices=( - ("eic", "I am Editor-in-charge"), - ("current", "All currently in processing"), + ("current", "Currently under consideration"), + ( + "current_noawaitingresub", + "Currently under consideration\n(excluding awaiting resubmission)" + ), ("historical", "All accessible history"), ), initial="current", @@ -277,17 +288,24 @@ class SubmissionPoolSearchForm(forms.Form): widget=forms.RadioSelect, choices=( ( - "Submission date", ( - ("recent", "most recent first"), - ("oldest", "oldest first"), + "Submission date ", ( + ("submission_recent", "most recent first"), + ("submission_oldest", "oldest first"), + ), + ), + ( + "Activity ", ( + ("activity_recent", "most recent first"), + ("activity_oldest", "oldest first"), ), ), ), - initial="recent", + initial="submission_recent", ) def __init__(self, *args, **kwargs): - user = kwargs.pop("user") + request = kwargs.pop("request") + user = request.user super().__init__(*args, **kwargs) if not user.contributor.is_ed_admin: # restrict journals to those of Colleges of user's Fellowships @@ -297,12 +315,9 @@ class SubmissionPoolSearchForm(forms.Form): self.fields["submitted_to"].queryset = Journal.objects.filter( college__in=college_id_list ) - if user.contributor.is_ed_admin: - # Remove 'I am Editor-in-charge' choice - self.fields["search_set"].choices = ( - ("current", "All currently in processing"), - ("historical", "All accessible history"), - ) + self.fields["editor_in_charge"].initial = ( + user.contributor.session_fellowship(request) + ) self.helper = FormHelper() self.helper.layout = Layout( Div( @@ -332,8 +347,9 @@ class SubmissionPoolSearchForm(forms.Form): css_class="row mb-0", ), Div( - Div(InlineRadios("search_set"), css_class="col"), - Div(InlineRadios("ordering"), css_class="col"), + Div(Field("versions"), css_class="col border"), + Div(Field("search_set"), css_class="col border"), + Div(Field("ordering"), css_class="col border"), css_class="row mb-0", ), ) @@ -342,12 +358,16 @@ class SubmissionPoolSearchForm(forms.Form): """ Return all Submission objects fitting search criteria. """ - if self.cleaned_data.get("search_set") == "eic": - submissions = Submission.objects.filter_for_eic(user) - elif self.cleaned_data.get("search_set") == "current": - submissions = Submission.objects.in_pool(user) - else: # include historical items - submissions = Submission.objects.in_pool(user, historical=True) + latest = self.cleaned_data.get("versions") == "latest" + search_set = self.cleaned_data.get("search_set") + historical = search_set == "historical" + submissions = Submission.objects.in_pool( + user, + latest=latest, + historical=historical, + ) + if search_set == "current_noawaitingresub": + submissions = submissions.exclude(status=Submission.AWAITING_RESUBMISSION) if self.cleaned_data.get("specialties"): submissions = submissions.filter( specialties__in=self.cleaned_data.get("specialties") @@ -451,8 +471,12 @@ class SubmissionPoolSearchForm(forms.Form): editor_in_charge=self.cleaned_data.get("editor_in_charge").contributor ) - if self.cleaned_data.get("ordering") == "oldest": + if self.cleaned_data.get("ordering") == "submission_oldest": submissions = submissions.order_by("submission_date") + elif self.cleaned_data.get("ordering") == "activity_recent": + submissions = submissions.order_by("-latest_activity") + elif self.cleaned_data.get("ordering") == "activity_oldest": + submissions = submissions.order_by("latest_activity") return submissions diff --git a/scipost_django/submissions/managers/submission.py b/scipost_django/submissions/managers/submission.py index 87dfc470c..c37265610 100644 --- a/scipost_django/submissions/managers/submission.py +++ b/scipost_django/submissions/managers/submission.py @@ -30,7 +30,7 @@ class SubmissionQuerySet(models.QuerySet): except AttributeError: return self.none() - def in_pool(self, user, historical: bool=False): + def in_pool(self, user, latest: bool=True, historical: bool=False): """ Filter for Submissions (current or historical) in user's pool. @@ -50,13 +50,15 @@ class SubmissionQuerySet(models.QuerySet): return self.none() qs = self + if latest: + qs = qs.latest() if not historical: - qs = qs.latest().filter(status__in=self.model.UNDER_CONSIDERATION) + qs = qs.filter(status__in=self.model.UNDER_CONSIDERATION) # for non-EdAdmin, filter: in Submission's Fellowship if not user.contributor.is_ed_admin: f_ids = user.contributor.fellowships.active() - qs = self.filter(fellows__in=f_ids) + qs = qs.filter(fellows__in=f_ids) # Fellows can't see incoming and (non-Senior) prescreening if user.contributor.is_active_senior_fellow: @@ -67,12 +69,12 @@ class SubmissionQuerySet(models.QuerySet): return qs.remove_COI(user) - def filter_for_eic(self, user): + def in_pool_filter_for_eic(self, user, historical: bool=False): """Return the set of Submissions the user is Editor-in-charge for. - If user is an Editorial Administrator: return the full pool. + If user is an Editorial Administrator: keep any EiC. """ - qs = self.in_pool(user) + qs = self.in_pool(user, historical) if user.is_authenticated and not user.contributor.is_ed_admin: qs = qs.filter(editor_in_charge__user=user) return qs diff --git a/scipost_django/submissions/views.py b/scipost_django/submissions/views.py index d686a368c..56e184b9c 100644 --- a/scipost_django/submissions/views.py +++ b/scipost_django/submissions/views.py @@ -714,7 +714,7 @@ def report_attachment(request, identifier_w_vn_nr, report_nr): if not report.is_vetted: # Only Admins and EICs are allowed to see non-vetted Report attachments. if ( - not Submission.objects.filter_for_eic(request.user) + not Submission.objects.in_pool_filter_for_eic(request.user) .filter(preprint__identifier_w_vn_nr=identifier_w_vn_nr) .exists() ): @@ -874,7 +874,7 @@ def pool(request, identifier_w_vn_nr=None): "recs_to_vote_on": recs_to_vote_on, "recs_current_voted": recs_current_voted, "assignments_to_consider": assignments_to_consider, - "form": SubmissionPoolSearchForm(initial=initial, user=request.user), + "form": SubmissionPoolSearchForm(initial=initial, request=request), } return render(request, "submissions/pool/pool.html", context) @@ -882,7 +882,7 @@ def pool(request, identifier_w_vn_nr=None): @login_required @fellowship_or_admin_required() def pool_hx_submissions_list(request): - form = SubmissionPoolSearchForm(request.POST or None, user=request.user) + form = SubmissionPoolSearchForm(request.POST or None, request=request) if form.is_valid(): submissions = form.search_results(request.user) else: @@ -892,8 +892,7 @@ def pool_hx_submissions_list(request): page_obj = paginator.get_page(page_nr) count = paginator.count start_index = page_obj.start_index - end_index = page_obj.end_index - context = {"count": count, "page_obj": page_obj, "start_index": start_index, "end_index": end_index,} + context = {"count": count, "page_obj": page_obj, "start_index": start_index,} return render(request, "submissions/pool/hx_submissions_list.html", context) @@ -1240,7 +1239,7 @@ def cycle_form_submit(request, identifier_w_vn_nr): Accessible to: Editor-in-charge and Editorial Administration """ submission = get_object_or_404( - Submission.objects.filter_for_eic(request.user), + Submission.objects.in_pool_filter_for_eic(request.user), preprint__identifier_w_vn_nr=identifier_w_vn_nr, ) @@ -1282,7 +1281,7 @@ def select_referee(request, identifier_w_vn_nr): create a new Profile and return to this page for further processing. """ submission = get_object_or_404( - Submission.objects.filter_for_eic(request.user), + Submission.objects.in_pool_filter_for_eic(request.user), preprint__identifier_w_vn_nr=identifier_w_vn_nr, ) @@ -1347,7 +1346,7 @@ def select_referee(request, identifier_w_vn_nr): @transaction.atomic def add_referee_profile(request, identifier_w_vn_nr): submission = get_object_or_404( - Submission.objects.filter_for_eic(request.user), + Submission.objects.in_pool_filter_for_eic(request.user), preprint__identifier_w_vn_nr=identifier_w_vn_nr, ) profile_form = SimpleProfileForm(request.POST or None) @@ -1380,7 +1379,7 @@ def invite_referee(request, identifier_w_vn_nr, profile_id, auto_reminders_allow If there is no associated Contributor, a registration invitation is included. """ submission = get_object_or_404( - Submission.objects.filter_for_eic(request.user), + Submission.objects.in_pool_filter_for_eic(request.user), preprint__identifier_w_vn_nr=identifier_w_vn_nr, ) profile = get_object_or_404(Profile, pk=profile_id) @@ -1501,7 +1500,7 @@ def ref_invitation_reminder(request, identifier_w_vn_nr, invitation_id): Accessible for: Editor-in-charge and Editorial Administration """ submission = get_object_or_404( - Submission.objects.filter_for_eic(request.user), + Submission.objects.in_pool_filter_for_eic(request.user), preprint__identifier_w_vn_nr=identifier_w_vn_nr, ) invitation = get_object_or_404( @@ -1673,7 +1672,7 @@ def cancel_ref_invitation(request, identifier_w_vn_nr, invitation_id): Accessible for: Editor-in-charge and Editorial Administration. """ try: - submissions = Submission.objects.filter_for_eic(request.user) + submissions = Submission.objects.in_pool_filter_for_eic(request.user) invitation = RefereeInvitation.objects.get( submission__in=submissions, pk=invitation_id ) @@ -1710,7 +1709,7 @@ def extend_refereeing_deadline(request, identifier_w_vn_nr, days): Accessible for: Editor-in-charge and Editorial Administration """ submission = get_object_or_404( - Submission.objects.filter_for_eic(request.user), + Submission.objects.in_pool_filter_for_eic(request.user), preprint__identifier_w_vn_nr=identifier_w_vn_nr, ) @@ -1746,7 +1745,7 @@ def set_refereeing_deadline(request, identifier_w_vn_nr): Accessible for: Editor-in-charge and Editorial Administration """ submission = get_object_or_404( - Submission.objects.filter_for_eic(request.user), + Submission.objects.in_pool_filter_for_eic(request.user), preprint__identifier_w_vn_nr=identifier_w_vn_nr, ) @@ -1797,7 +1796,7 @@ def close_refereeing_round(request, identifier_w_vn_nr): Accessible for: Editor-in-charge and Editorial Administration. """ submission = get_object_or_404( - Submission.objects.filter_for_eic(request.user), + Submission.objects.in_pool_filter_for_eic(request.user), preprint__identifier_w_vn_nr=identifier_w_vn_nr, ) @@ -1839,7 +1838,7 @@ def communication(request, identifier_w_vn_nr, comtype, referee_id=None): referee = None if comtype in ["EtoA", "EtoR", "EtoS"]: # Editor to {Author, Referee, Editorial Administration} - submissions_qs = Submission.objects.filter_for_eic(request.user) + submissions_qs = Submission.objects.in_pool_filter_for_eic(request.user) elif comtype == "AtoE": # Author to Editor submissions_qs = Submission.objects.filter_for_author(request.user) @@ -1920,7 +1919,7 @@ def eic_recommendation(request, identifier_w_vn_nr): Accessible for: Editor-in-charge and Editorial Administration """ submission = get_object_or_404( - Submission.objects.filter_for_eic(request.user), + Submission.objects.in_pool_filter_for_eic(request.user), preprint__identifier_w_vn_nr=identifier_w_vn_nr, ) @@ -1991,7 +1990,7 @@ def reformulate_eic_recommendation(request, identifier_w_vn_nr): Accessible for: Editor-in-charge and Editorial Administration. """ submission = get_object_or_404( - Submission.objects.filter_for_eic(request.user), + Submission.objects.in_pool_filter_for_eic(request.user), preprint__identifier_w_vn_nr=identifier_w_vn_nr, ) recommendation = submission.eicrecommendations.last() @@ -2152,7 +2151,9 @@ def submit_report(request, identifier_w_vn_nr): @fellowship_or_admin_required() def vet_submitted_reports_list(request): """List Reports with status `unvetted`.""" - submissions = get_list_or_404(Submission.objects.filter_for_eic(request.user)) + submissions = get_list_or_404( + Submission.objects.in_pool_filter_for_eic(request.user) + ) reports_to_vet = ( Report.objects.filter(submission__in=submissions) .awaiting_vetting() @@ -2178,7 +2179,7 @@ def vet_submitted_report(request, report_id): # Vetting Editors may vote on everything. report = get_object_or_404(Report.objects.awaiting_vetting(), id=report_id) else: - submissions = Submission.objects.filter_for_eic(request.user) + submissions = Submission.objects.in_pool_filter_for_eic(request.user) report = get_object_or_404( Report.objects.filter(submission__in=submissions).awaiting_vetting(), id=report_id, -- GitLab