Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions src/copyediting/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ class CopyeditAdmin(admin_utils.ArticleFKModelAdmin):
"editor_note",
"copyeditor_note",
)
raw_id_fields = ("article", "copyeditor", "editor")
filter_horizontal = ("files_for_copyediting", "copyeditor_files")
raw_id_fields = ("article", "copyeditor", "editor", "files_for_copyediting", "copyeditor_files")

inlines = [admin_utils.AuthorReviewInline]

Expand All @@ -62,9 +61,7 @@ class AuthorAdmin(admin.ModelAdmin):
"assignment__editor_note",
"assignment__copyeditor_note",
)
raw_id_fields = ("author", "assignment")
filter_horizontal = ("files_updated",)
exclude = ("files_updated",)
raw_id_fields = ("author", "assignment", "files_updated")

def _journal(self, obj):
return obj.assignment.article.journal.code if obj else ""
Expand Down
15 changes: 6 additions & 9 deletions src/copyediting/logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,31 +145,28 @@ def handle_file_post(request, copyedit):
return errors


def accept_copyedit(copyedit, article, request):
def accept_copyedit(copyedit, article, request, email_data=None, skip=False):
"""
Raises an event when a copyedit is accepted
:param copyedit: CopyeditAssignment object
:param article: Article object
:param request: HttpRequest object
:param email_data: EmailData dataclass instance
:param skip: bool, if True the notification email is skipped
:return: None
"""
user_message_content = request.POST.get("accept_note")

kwargs = {
"copyedit_assignment": copyedit,
"article": article,
"user_message_content": user_message_content,
"email_data": email_data,
"request": request,
"skip": True if "skip" in request.POST else False,
"skip": skip,
}

event_logic.Events.raise_event(event_logic.Events.ON_COPYEDIT_ACKNOWLEDGE, **kwargs)

copyedit.copyedit_accepted = timezone.now()

if "skip" not in request.POST:
copyedit.copyedit_acknowledged = True

copyedit.copyedit_acknowledged = True
copyedit.save()


Expand Down
49 changes: 48 additions & 1 deletion src/copyediting/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ def setUpTestData(cls):
"typesetter@janeway.systems",
["editor"],
journal=cls.journal_one,
atrrs={"is_active": True},
)
cls.editor.is_active = True
cls.editor.save()
cls.copyeditor = helpers.create_user(
"copyeditor@janeway.systems",
["copyeditor"],
Expand Down Expand Up @@ -130,3 +131,49 @@ def test_active_article_review_task_200s(self):
response.status_code,
200,
)

def test_accept_copyedit_sends_email_and_marks_acknowledged(self):
"""Accepting with send sets copyedit_accepted and copyedit_acknowledged."""
task = models.CopyeditAssignment.objects.create(
article=self.active_article,
copyeditor=self.copyeditor,
editor=self.editor,
copyeditor_completed=timezone.now(),
)
self.client.force_login(self.editor)
self.client.post(
reverse(
"accept_copyedit",
kwargs={
"article_id": self.active_article.pk,
"copyedit_id": task.pk,
},
),
{"subject": "Thank you", "body": "Thank you for your work."},
)
task.refresh_from_db()
self.assertIsNotNone(task.copyedit_accepted)
self.assertTrue(task.copyedit_acknowledged)

def test_accept_copyedit_skip_marks_acknowledged_without_email(self):
"""Accepting with skip sets copyedit_accepted and copyedit_acknowledged without sending email."""
task = models.CopyeditAssignment.objects.create(
article=self.active_article,
copyeditor=self.copyeditor,
editor=self.editor,
copyeditor_completed=timezone.now(),
)
self.client.force_login(self.editor)
self.client.post(
reverse(
"accept_copyedit",
kwargs={
"article_id": self.active_article.pk,
"copyedit_id": task.pk,
},
),
{"skip": "True"},
)
task.refresh_from_db()
self.assertIsNotNone(task.copyedit_accepted)
self.assertTrue(task.copyedit_acknowledged)
5 changes: 5 additions & 0 deletions src/copyediting/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
views.editor_review,
name="editor_review",
),
re_path(
r"^article/(?P<article_id>\d+)/assignment/(?P<copyedit_id>\d+)/accept/$",
views.accept_copyedit,
name="accept_copyedit",
),
re_path(
r"^article/(?P<article_id>\d+)/assignment/(?P<copyedit_id>\d+)/author_review/(?P<author_review_id>\d+)/$",
views.request_author_copyedit,
Expand Down
68 changes: 54 additions & 14 deletions src/copyediting/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from django.http import Http404
from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
from django.utils.translation import gettext as _

from copyediting import models, logic, forms
from core import (
Expand All @@ -21,12 +20,10 @@
)
from events import logic as event_logic
from security.decorators import (
production_user_or_editor_required,
copyeditor_user_required,
copyeditor_for_copyedit_required,
article_author_required,
editor_user_required,
senior_editor_user_required,
any_editor_user_required,
)

Expand Down Expand Up @@ -547,14 +544,7 @@ def editor_review(request, article_id, copyedit_id):
)

if request.POST:
if "accept_note" in request.POST:
logic.accept_copyedit(copyedit, article, request)

return redirect(
reverse("article_copyediting", kwargs={"article_id": article.id})
)

elif (
if (
"author_review" in request.POST
or author_review_form.CONFIRMED_BUTTON_NAME in request.POST
):
Expand Down Expand Up @@ -591,9 +581,6 @@ def editor_review(request, article_id, copyedit_id):
context = {
"article": article,
"copyedit": copyedit,
"accept_message": logic.get_copyedit_message(
request, article, copyedit, "copyeditor_ack"
),
"reopen_message": logic.get_copyedit_message(
request, article, copyedit, "copyeditor_reopen_task"
),
Expand All @@ -603,6 +590,59 @@ def editor_review(request, article_id, copyedit_id):
return render(request, template, context)


@editor_user_required
def accept_copyedit(request, article_id, copyedit_id):
"""
Allows an editor to accept a completed copyedit and optionally notify the copyeditor.
"""
article = get_object_or_404(
submission_models.Article,
pk=article_id,
journal=request.journal,
)
copyedit = get_object_or_404(
models.CopyeditAssignment,
pk=copyedit_id,
article=article,
)
email_context = logic.get_copyeditor_notification_context(request, article, copyedit)
form = core_forms.SettingEmailForm(
setting_name="copyeditor_ack",
email_context=email_context,
request=request,
)

if request.POST:
skip = "skip" in request.POST
form = core_forms.SettingEmailForm(
request.POST,
request.FILES,
setting_name="copyeditor_ack",
email_context=email_context,
request=request,
)
if form.is_valid() or skip:
logic.accept_copyedit(
copyedit,
article,
request,
email_data=form.as_dataclass() if form.is_valid() else None,
skip=skip,
)
return redirect(
reverse("article_copyediting", kwargs={"article_id": article.id})
)

template = "copyediting/accept_copyedit.html"
context = {
"article": article,
"copyedit": copyedit,
"form": form,
}

return render(request, template, context)


@editor_user_required
def request_author_copyedit(request, article_id, copyedit_id, author_review_id):
"""
Expand Down
38 changes: 38 additions & 0 deletions src/templates/admin/copyediting/accept_copyedit.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{% extends "admin/core/base.html" %}
{% load static %}

{% block title %}Accept Copyedit{% endblock %}
{% block title-section %}Accept Copyedit{% endblock %}
{% block title-sub %}#{{ article.pk }} / {{ article.correspondence_author.last_name }} / {{ article.safe_title }}{% endblock %}

{% block breadcrumbs %}
{{ block.super }}
{% include "elements/breadcrumbs/copyediting_base.html" with subpage="yes" %}
<li>Review Copyediting</li>
{% endblock breadcrumbs %}

{% block body %}

<div class="box">
<div class="title-area">
<h2>Accept Copyedit</h2>
</div>
<div class="content">
<p>You can write a note to the copyeditor thanking them for their time, or skip the email.</p>
<div class="card">
<div class="card-divider">
<h4>To {{ copyedit.copyeditor.full_name }}</h4>
<h5>From {{ request.user.full_name }}</h5>
</div>
</div>
{% url 'editor_review' article.pk copyedit.pk as cancel_url %}
{% include 'admin/elements/email_form.html' with form=form skip=1 cancel_url=cancel_url %}
</div>
</div>

{% endblock %}

{% block js %}
{{ block.super }}
{{ form.media.js }}
{% endblock js %}
22 changes: 1 addition & 21 deletions src/templates/admin/copyediting/editor_review.html
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ <h2>Actions</h2>
<div class="content">
{% if copyedit.actions_available %}
<ul class="menu vertical actions">
<li><a href="#" data-open="accept-modal"><i class="fa fa-check-circle action-icon">&nbsp;</i>Accept Copyedit</a></li>
<li><a href="{% url 'accept_copyedit' article.pk copyedit.pk %}"><i class="fa fa-check-circle action-icon">&nbsp;</i>Accept Copyedit</a></li>
<li>
<form id="copyediting_author_review_assignment" method="POST">
{% csrf_token %}
Expand Down Expand Up @@ -204,26 +204,6 @@ <h2>Log</h2>
</div>
</div>

<div class="reveal" id="accept-modal" data-reveal data-animation-in="slide-in-up"
data-animation-out="slide-out-down">
<div class="card">
<div class="card-divider">
<h4><i class="fa fa-check-circle">&nbsp;</i>Accept Copyedit</h4>
</div>
<div class="card-section">
<p>You can write a note to the copyeditor thanking them for their time.</p>
<form method="POST">
{% csrf_token %}
<textarea name="accept_note">{{ accept_message|safe|linebreaksbr }}</textarea>
<button name="accept" type="submit" class="button success"><i class="fa fa-envelope-o">&nbsp;</i>Send
</button>
</form>
</div>
</div>
<button class="close-button" data-close aria-label="Close modal" type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>

<div class="reveal" id="reset-modal" data-reveal data-animation-in="slide-in-up"
data-animation-out="slide-out-down">
Expand Down
14 changes: 6 additions & 8 deletions src/utils/transactional_emails.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
models as core_models,
)
from review import logic as review_logic
from review.const import EditorialDecisions as ED


def send_reviewer_withdrawl_notice(**kwargs):
Expand Down Expand Up @@ -921,7 +920,7 @@ def send_author_copyedit_deleted(**kwargs):
def send_copyedit_ack(**kwargs):
request = kwargs["request"]
copyedit_assignment = kwargs["copyedit_assignment"]
user_message_content = kwargs["user_message_content"]
email_data = kwargs.get("email_data")
skip = kwargs.get("skip", False)

description = "{0} has acknowledged copyediting for {1}".format(
Expand All @@ -937,11 +936,11 @@ def send_copyedit_ack(**kwargs):
"target": copyedit_assignment.article,
}

notify_helpers.send_email_with_body_from_user(
core_email.send_email(
copyedit_assignment.copyeditor,
email_data,
request,
"subject_copyeditor_ack",
copyedit_assignment.copyeditor.email,
user_message_content,
article=copyedit_assignment.article,
log_dict=log_dict,
)
notify_helpers.send_slack(request, description, ["slack_editors"])
Expand Down Expand Up @@ -1924,8 +1923,7 @@ def preprint_new_version(**kwargs):
description = "{author} has submitted a new {obj} version.".format(
author=request.user.full_name(),
obj=request.repository.object_name,
title=preprint.title,
)
)
log_dict = {
"level": "Info",
"action_text": description,
Expand Down
Loading