From a1a705865113e984b9caeff16236397007cd3c8b Mon Sep 17 00:00:00 2001 From: George Katsikas <giorgakis.katsikas@gmail.com> Date: Thu, 1 Aug 2024 17:07:22 +0200 Subject: [PATCH] generalize editorial communications tool add links for author - edadmin communication & viceversa fixes #299 --- .../submissions/managers/communication.py | 8 ++-- .../submissions/_communication_thread.html | 38 +++------------- .../_submission_author_information.html | 1 + .../templates/submissions/communication.html | 8 ++-- .../submissions/pool/editorial_page.html | 9 ++-- scipost_django/submissions/utils.py | 5 +++ scipost_django/submissions/views/__init__.py | 43 +++++++++++-------- 7 files changed, 52 insertions(+), 60 deletions(-) diff --git a/scipost_django/submissions/managers/communication.py b/scipost_django/submissions/managers/communication.py index dbb7fe1b6..e1cd8ecb5 100644 --- a/scipost_django/submissions/managers/communication.py +++ b/scipost_django/submissions/managers/communication.py @@ -7,9 +7,9 @@ from django.db import models class EditorialCommunicationQuerySet(models.QuerySet): def for_referees(self): - """Only return communication between Referees and Editors.""" - return self.filter(comtype__in=["EtoR", "RtoE"]) + """Only return communication related to Referees.""" + return self.filter(comtype__contains="R") def for_authors(self): - """Only return communication between Authors and Editors.""" - return self.filter(comtype__in=["EtoA", "AtoE"]) + """Only return communication related to Authors.""" + return self.filter(comtype__contains="A") diff --git a/scipost_django/submissions/templates/submissions/_communication_thread.html b/scipost_django/submissions/templates/submissions/_communication_thread.html index d9b024d9b..5c1a6e949 100644 --- a/scipost_django/submissions/templates/submissions/_communication_thread.html +++ b/scipost_django/submissions/templates/submissions/_communication_thread.html @@ -1,45 +1,19 @@ <ul class="mt-2 communications {{ css_class }}"> + {% for comm in communication %} - <li class="date"><span>{{ comm.timestamp|date:'d F Y' }}</span></li> + <li class="date"> + <span>{{ comm.timestamp|date:'d F Y' }}</span> + </li> <li class="comm comm-{{ comm.comtype }}"> <span class="datetime">{{ comm.timestamp|date:'d F Y G:i' }}</span> <span class="time">{{ comm.timestamp|date:'G:i' }}</span> <div class="content"> - <span class="header"> - {% if comm.comtype == 'RtoE' %} - From {{ comm.referee.user.first_name }} {{ comm.referee.user.last_name }} to {{ reader_is_editor|yesno:'you,Editor-in-charge' }} - {% elif comm.comtype == 'EtoR' %} - From {{ reader_is_editor|yesno:'you,Editor-in-charge' }} to - {% if comm.referee %} - {{ comm.referee.user.first_name }} {{ comm.referee.user.last_name }} - {% else %} - referee (?) - {% endif %} - {% elif comm.comtype == 'AtoE' %} - From - {% if comm.referee %} - {{ comm.referee.user.first_name }} {{ comm.referee.user.last_name }} - {% else %} - author (?) - {% endif %} - to {{ reader_is_editor|yesno:'you,Editor-in-charge' }} - {% elif comm.comtype == 'EtoA' %} - From {{ reader_is_editor|yesno:'you,Editor-in-charge' }} to - {% if comm.referee %} - {{ comm.referee.user.first_name }} {{ comm.referee.user.last_name }} - {% else %} - author (?) - {% endif %} - {% elif comm.comtype == 'StoE' %} - From Editorial Administration to {{ reader_is_editor|yesno:'you,Editor-in-charge' }} - {% elif comm.comtype == 'EtoS' %} - From {{ reader_is_editor|yesno:'you,Editor-in-charge' }} to Editorial Administration - {% endif %} - </span> + <span class="header">From {{ comm.author_name }} to {{ comm.recipient_name }}</span> <p class="comm-text">{{ comm.text|linebreaksbr }}</p> </div> </li> {% empty %} <li>There have been no communications.</li> {% endfor %} + </ul> diff --git a/scipost_django/submissions/templates/submissions/_submission_author_information.html b/scipost_django/submissions/templates/submissions/_submission_author_information.html index a926de48d..58fbbf75e 100644 --- a/scipost_django/submissions/templates/submissions/_submission_author_information.html +++ b/scipost_django/submissions/templates/submissions/_submission_author_information.html @@ -96,6 +96,7 @@ {% if submission.editor_in_charge %} <a href="{% url 'submissions:communication' submission.preprint.identifier_w_vn_nr 'AtoE' %}">Write to the Editor-in-charge</a> {% endif %} + <a href="{% url 'submissions:communication' submission.preprint.identifier_w_vn_nr 'AtoS' %}">Write to the SciPost Editorial Administration</a> {% include 'submissions/_communication_thread.html' with communication=submission.editorial_communications.for_authors css_class='wide' %} </div> </div> diff --git a/scipost_django/submissions/templates/submissions/communication.html b/scipost_django/submissions/templates/submissions/communication.html index 6c653bce6..16bc4981d 100644 --- a/scipost_django/submissions/templates/submissions/communication.html +++ b/scipost_django/submissions/templates/submissions/communication.html @@ -26,13 +26,13 @@ <div class="card bg-light mb-3"> <div class="card-body"> <h1 class="pb-0">Send a Communication</h1> - {% if comtype == 'EtoA' %} + {% if comtype|last == 'A' %} <h3 class="mb-0">to the submitting Author of Submission</h3> - {% elif comtype == 'AtoE' or comtype == 'RtoE' or comtype == 'StoE' %} + {% elif comtype|last == 'E' %} <h3 class="mb-0">to the Editor-in-charge of Submission</h3> - {% elif comtype == 'EtoR' %} + {% elif comtype|last == 'R' %} <h3 class="mb-0">to Referee of Submission</h3> - {% elif comtype == 'EtoS' %} + {% elif comtype|last == 'S' %} <h3 class="mb-0">to SciPost Editorial Administrators</h3> {% endif %} </div> diff --git a/scipost_django/submissions/templates/submissions/pool/editorial_page.html b/scipost_django/submissions/templates/submissions/pool/editorial_page.html index 248f463f1..543a66458 100644 --- a/scipost_django/submissions/templates/submissions/pool/editorial_page.html +++ b/scipost_django/submissions/templates/submissions/pool/editorial_page.html @@ -497,14 +497,17 @@ <li><a href="{% url 'submissions:communication' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr comtype='EtoS' %}">Draft and send a communication with SciPost Editorial Administration</a></li> {% endif %} {% if is_ed_admin %} - <li><a href="{% url 'submissions:communication' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr comtype='StoE' %}">Draft and send a communication as Editorial Administrator to the Editor-in-charge</a></li> + {% if submission.editor_in_charge %} + <li><a href="{% url 'submissions:communication' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr comtype='StoE' %}">Draft and send a communication as Editorial Administrator to the Editor-in-charge</a></li> + {% endif %} + <li><a href="{% url 'submissions:communication' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr comtype='StoA' %}">Draft and send a communication as Editorial Administrator to the submitting Author</a></li> {% endif %} </ul> {% if submission.editor_in_charge == request.user.contributor %} - {% include 'submissions/_communication_thread.html' with communication=submission.editorial_communications.all css_class='wide' reader_is_editor=1 %} + {% include 'submissions/_communication_thread.html' with communication=submission.editorial_communications.all css_class='wide' %} {% else %} - {% include 'submissions/_communication_thread.html' with communication=submission.editorial_communications.all css_class='wide' reader_is_editor=0 %} + {% include 'submissions/_communication_thread.html' with communication=submission.editorial_communications.all css_class='wide' %} {% endif %} <h2 class="mt-3" id="events">Events</h2> diff --git a/scipost_django/submissions/utils.py b/scipost_django/submissions/utils.py index 8cb1e566c..344c9558b 100644 --- a/scipost_django/submissions/utils.py +++ b/scipost_django/submissions/utils.py @@ -735,6 +735,11 @@ class SubmissionUtils(BaseMailUtil): raise ValueError("No communication attribute found. Please `.load()` it.") valid_comtypes = [comtype[0] for comtype in ED_COMM_CHOICES] + + # Referee to Author communication is strictly forbidden + valid_comtypes.remove("RtoA") + valid_comtypes.remove("AtoR") + if communication.comtype not in valid_comtypes: raise ValueError( f"Invalid comtype {communication.comtype}. " diff --git a/scipost_django/submissions/views/__init__.py b/scipost_django/submissions/views/__init__.py index 91f826228..f8c4626a3 100644 --- a/scipost_django/submissions/views/__init__.py +++ b/scipost_django/submissions/views/__init__.py @@ -3,6 +3,7 @@ __license__ = "AGPL v3" import datetime +import re from django.core.paginator import Paginator from django.template.response import TemplateResponse @@ -43,6 +44,7 @@ from scipost.permissions import ( ) from ..constants import ( + ED_COMM_CHOICES, STATUS_VETTED, STATUS_DRAFT, CYCLE_DIRECT_REC, @@ -2023,19 +2025,26 @@ def communication(request, identifier_w_vn_nr, comtype, referee_id=None): Communication may be between two of: editor-in-charge, author and referee. """ referee = None - if comtype in ["EtoA", "EtoR", "EtoS"]: - # Editor to {Author, Referee, Editorial Administration} + author, recipient = re.match(r"(\w)to(\w)", comtype).groups() + + valid_comtypes = [comtype[0] for comtype in ED_COMM_CHOICES] + + # Referee to Author communication is strictly forbidden + valid_comtypes.remove("RtoA") + valid_comtypes.remove("AtoR") + + if comtype not in valid_comtypes: + raise Http404("Invalid communication type") + + if author == "E": submissions_qs = Submission.objects.in_pool_filter_for_eic( request.user, latest=False, historical=True, ) - elif comtype == "AtoE": - # Author to Editor + elif author == "A": submissions_qs = Submission.objects.filter_for_author(request.user) - referee = request.user.contributor - elif comtype == "RtoE": - # Referee to Editor (Contributor account required) + elif author == "R": if not hasattr(request.user, "contributor"): # Raise PermissionDenied to let the user know something is wrong with its account. raise PermissionDenied @@ -2044,8 +2053,7 @@ def communication(request, identifier_w_vn_nr, comtype, referee_id=None): referee_invitations__referee__user=request.user ) referee = request.user.contributor - elif comtype == "StoE": - # Editorial Administration to Editor + elif author == "S": if not request.user.has_perm("scipost.can_oversee_refereeing"): raise PermissionDenied submissions_qs = Submission.objects.in_pool( @@ -2055,7 +2063,7 @@ def communication(request, identifier_w_vn_nr, comtype, referee_id=None): referee = request.user.contributor else: # Invalid commtype in the url! - raise Http404 + raise Http404("Invalid communication type") # Uniquify and get the showpiece itself or return 404 submissions_qs = submissions_qs.distinct() @@ -2063,12 +2071,12 @@ def communication(request, identifier_w_vn_nr, comtype, referee_id=None): submissions_qs, preprint__identifier_w_vn_nr=identifier_w_vn_nr ) - if referee_id and comtype in ["EtoA", "EtoR", "EtoS"]: + if recipient == "R" and referee_id: # Get the Contributor to communicate with if not already defined (`Eto?` communication) # To Fix: Assuming the Editorial Administrator won't make any `referee_id` mistakes referee = get_object_or_404(Contributor.objects.active(), pk=referee_id) - elif comtype == "EtoA": - referee = submission.submitted_by + else: + referee = None form = EditorialCommunicationForm(request.POST or None) if form.is_valid(): @@ -2084,22 +2092,23 @@ def communication(request, identifier_w_vn_nr, comtype, referee_id=None): except Exception as e: messages.error( request, - "Communication submitted, but an error occurred while sending the email: " + str(e), + "Communication submitted, but an error occurred while sending the email: " + + str(e), ) sentry_sdk.capture_exception(e) return redirect(submission.get_absolute_url()) messages.success(request, "Communication submitted") - if comtype in ["EtoA", "EtoR", "EtoS"]: + if author == "E": return redirect( reverse( "submissions:editorial_page", kwargs={"identifier_w_vn_nr": identifier_w_vn_nr}, ) ) - elif comtype == "AtoE": + elif author == "A": return redirect(submission.get_absolute_url()) - elif comtype == "StoE": + elif author == "S": return redirect(reverse("submissions:pool:pool")) return redirect(submission.get_absolute_url()) -- GitLab