From b76519b967a4ff0f254a2880b028daa062cae6c0 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Thu, 9 Nov 2017 12:23:52 +0000 Subject: [PATCH 01/34] Added execute to saxon.jar. --- src/transform/cassius/cassius-import/bin/saxon9.jar | Bin 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 src/transform/cassius/cassius-import/bin/saxon9.jar diff --git a/src/transform/cassius/cassius-import/bin/saxon9.jar b/src/transform/cassius/cassius-import/bin/saxon9.jar old mode 100644 new mode 100755 From ddc773d92d867be036f091cd73e0756edc2f8c1b Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Fri, 10 Nov 2017 10:22:42 +0000 Subject: [PATCH 02/34] When saving a review form we now pass the assignment and check that the assignment.form is the element.form. --- src/review/models.py | 4 ++-- src/review/views.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/review/models.py b/src/review/models.py index c5949da4c7..dca6d19a18 100644 --- a/src/review/models.py +++ b/src/review/models.py @@ -109,9 +109,9 @@ class ReviewAssignment(models.Model): def review_form_answers(self): return ReviewAssignmentAnswer.objects.filter(assignment=self).order_by('element__order') - def save_review_form(self, review_form): + def save_review_form(self, review_form, assignment): for k, v in review_form.cleaned_data.items(): - form_element = ReviewFormElement.objects.get(name=k) + form_element = ReviewFormElement.objects.get(reviewform=assignment.form, name=k) ReviewAssignmentAnswer.objects.create( assignment=self, element=form_element, diff --git a/src/review/views.py b/src/review/views.py index 9e2738220b..cd4119f961 100644 --- a/src/review/views.py +++ b/src/review/views.py @@ -591,7 +591,7 @@ def do_review(request, assignment_id): if form.is_valid() and decision_form.is_valid(): decision_form.save() - assignment.save_review_form(form) + assignment.save_review_form(form, assignment) assignment.date_complete = timezone.now() assignment.is_complete = True assignment.save() From aac822acf647bb8a343dbbc43959143a62e3668c Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Fri, 10 Nov 2017 10:26:25 +0000 Subject: [PATCH 03/34] Updated models and help text to reflect annotation review styles. --- src/review/models.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/review/models.py b/src/review/models.py index dca6d19a18..ef3f566fd0 100644 --- a/src/review/models.py +++ b/src/review/models.py @@ -37,7 +37,7 @@ def review_decision(): def review_type(): return ( ('traditional', 'Traditional'), - ('annotation', 'Annotation'), + #('annotation', 'Annotation'), ) @@ -82,8 +82,7 @@ class ReviewAssignment(models.Model): "have any competing interests please add them here. " "EG. 'This study was paid for by corp xyz.'.") review_type = models.CharField(max_length=20, choices=review_type(), default='traditional', - help_text='Traditional review uses a form set, annotation review ' - 'is freeform using hypothes.is') + help_text='Currently only traditional, form based, review is available.') visibility = models.CharField(max_length=20, choices=review_visibilty(), default='blind') form = models.ForeignKey('ReviewForm') access_code = models.CharField(max_length=100, blank=True, null=True) From f4a90a1a1147b4f32549b9c3c61637ff0159ae9d Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Fri, 10 Nov 2017 10:57:03 +0000 Subject: [PATCH 04/34] Added option to use an existing figure file as a galley image. --- src/production/logic.py | 24 ++++++++++++++++++- src/production/views.py | 6 ++++- .../admin/production/edit_galley.html | 13 ++++++++-- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/production/logic.py b/src/production/logic.py index ec28361d5e..a09cb23a55 100644 --- a/src/production/logic.py +++ b/src/production/logic.py @@ -89,6 +89,23 @@ def save_galley_image(galley, request, uploaded_file, label="Galley Image", fixe return new_file +def use_data_file_as_galley_image(galley, request, label): + file_id = request.POST.get('datafile') + + if file_id: + try: + file = core_models.File.objects.get(pk=file_id) + file.original_filename = request.POST.get('file_name') + file.save() + galley.images.add(file) + messages.add_message(request, messages.SUCCESS, 'File added.') + except core_models.File.DoesNotExist: + messages.add_message(request, messages.WARNING, 'No file with given ID found.') + + + + + def save_galley_css(galley, request, uploaded_file, filename, label="Galley Image"): new_file = files.save_file_to_article(uploaded_file, galley.article, request.user) new_file.is_galley = False @@ -215,7 +232,12 @@ def handle_delete_request(request, galley, typeset_task=None, article=None, page file_to_delete = core_models.File.objects.get(pk=file_id) if file_to_delete.pk in galley.article.all_galley_file_pks(): messages.add_message(request, messages.INFO, 'File deleted') - file_to_delete.delete() + + # Check if this is a data file, and if it is remove it, dont delete it. + if file_to_delete in galley.article.data_figure_files.all(): + galley.images.remove(file_to_delete) + else: + file_to_delete.delete() except core_models.File.DoesNotExist: messages.add_message(request, messages.WARNING, 'File not found') diff --git a/src/production/views.py b/src/production/views.py index 6715b478ec..59e9e397c8 100644 --- a/src/production/views.py +++ b/src/production/views.py @@ -446,6 +446,8 @@ def edit_galley(request, galley_id, typeset_id=None, article_id=None): label = request.POST.get('label') if 'fixed-image-upload' in request.POST: + if request.POST.get('datafile') != None: + logic.use_data_file_as_galley_image(galley, request, label) for uploaded_file in request.FILES.getlist('image'): logic.save_galley_image(galley, request, uploaded_file, label, fixed=True) if 'image-upload' in request.POST: @@ -474,7 +476,9 @@ def edit_galley(request, galley_id, typeset_id=None, article_id=None): 'galley': galley, 'article': galley.article, 'image_names': logic.get_image_names(galley), - 'return_url': return_url + 'return_url': return_url, + 'data_files': article.data_figure_files.all(), + 'galley_images': galley.images.all() } return render(request, template, context) diff --git a/src/templates/admin/production/edit_galley.html b/src/templates/admin/production/edit_galley.html index 06507afd04..f2c0959ae3 100644 --- a/src/templates/admin/production/edit_galley.html +++ b/src/templates/admin/production/edit_galley.html @@ -126,7 +126,7 @@

Image Files

History Delete -
+ {% csrf_token %} {% for image in galley.images.all %} {% can_view_file image as can_view_file_flag %} @@ -176,12 +176,21 @@
{{ element }}
+ {% if data_files %} +

Or, you can choose an existing figure file.

+ + {% endif %}
From 145244072508c1aa5b00e2fde63b1d5c6cdfadf8 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Fri, 10 Nov 2017 10:58:08 +0000 Subject: [PATCH 05/34] Added label to galley image file dropdown. AA --- src/templates/admin/production/edit_galley.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/admin/production/edit_galley.html b/src/templates/admin/production/edit_galley.html index f2c0959ae3..0e10886fb7 100644 --- a/src/templates/admin/production/edit_galley.html +++ b/src/templates/admin/production/edit_galley.html @@ -181,7 +181,7 @@
{{ element }}
{% endif %} From 3e9f3cf2d3a84255b0e8e1bba086bd30261b4c50 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Fri, 10 Nov 2017 11:17:52 +0000 Subject: [PATCH 06/34] Django 1.11 no longer authenticates inactive users. Message update, logic updated. --- src/core/views.py | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/core/views.py b/src/core/views.py index fb88c841d7..5a991e3ee3 100644 --- a/src/core/views.py +++ b/src/core/views.py @@ -67,29 +67,27 @@ def user_login(request): user = authenticate(username=user, password=pawd) if user is not None: - if user.is_active: - login(request, user) - messages.info(request, 'Login successful.') - logic.clear_bad_login_attempts(request) - - orcid_token = request.POST.get('orcid_token', None) - if orcid_token: - try: - token_obj = models.OrcidToken.objects.get(token=orcid_token, expiry__gt=timezone.now()) - user.orcid = token_obj.orcid - user.save() - token_obj.delete() - except models.OrcidToken.DoesNotExist: - pass - - if request.GET.get('next'): - return redirect(request.GET.get('next')) - else: - return redirect(reverse('website_index')) + login(request, user) + messages.info(request, 'Login successful.') + logic.clear_bad_login_attempts(request) + + orcid_token = request.POST.get('orcid_token', None) + if orcid_token: + try: + token_obj = models.OrcidToken.objects.get(token=orcid_token, expiry__gt=timezone.now()) + user.orcid = token_obj.orcid + user.save() + token_obj.delete() + except models.OrcidToken.DoesNotExist: + pass + + if request.GET.get('next'): + return redirect(request.GET.get('next')) else: - messages.add_message(request, messages.ERROR, 'User account is not active.') + return redirect(reverse('website_index')) else: - messages.add_message(request, messages.ERROR, 'Account not found with those details.') + messages.add_message(request, messages.ERROR, 'Account not found or account not active. Please ensure' + 'you have activated your account.') util_models.LogEntry.add_entry(types='Authentication', description='Failed login attempt for user {0}'.format( request.POST.get('user_name')), From e2d73dd9c8cf50693d87432e83b60f8e59d3dc3c Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Fri, 10 Nov 2017 11:40:32 +0000 Subject: [PATCH 07/34] Updated article links to display that they are external. --- src/static/OLH/css/app.css | 3 ++ src/static/default/css/bootstrap.css | 6 +++- src/themes/OLH/assets/scss/app.scss | 4 +++ .../elements/journal/box_article.html | 2 +- .../OLH/templates/journal/issue_display.html | 29 +----------------- src/themes/OLH/templates/journal/search.html | 30 +------------------ src/themes/default/assets/css/bootstrap.css | 6 +++- .../templates/elements/article_listing.html | 2 +- 8 files changed, 21 insertions(+), 61 deletions(-) diff --git a/src/static/OLH/css/app.css b/src/static/OLH/css/app.css index a281fc8e57..9035fc475c 100644 --- a/src/static/OLH/css/app.css +++ b/src/static/OLH/css/app.css @@ -5215,3 +5215,6 @@ button.list-group-item-danger.active:focus { .subjectbutton { padding-top: 0 !important; padding-bottom: 0 !important; } + +.small-icon-text { + font-size: 17px; } diff --git a/src/static/default/css/bootstrap.css b/src/static/default/css/bootstrap.css index 4040cf2ceb..cd7328dc24 100644 --- a/src/static/default/css/bootstrap.css +++ b/src/static/default/css/bootstrap.css @@ -9608,4 +9608,8 @@ footer svg { a.profilelink:link{ color: #FFFFFF; -} \ No newline at end of file +} + +.small-icon-text { + font-size: 17px !important; +} diff --git a/src/themes/OLH/assets/scss/app.scss b/src/themes/OLH/assets/scss/app.scss index 29f10a1f38..1d89c86eb4 100644 --- a/src/themes/OLH/assets/scss/app.scss +++ b/src/themes/OLH/assets/scss/app.scss @@ -1107,4 +1107,8 @@ button.list-group-item-danger.active:focus { .subjectbutton { padding-top: 0 !important; padding-bottom: 0 !important; +} + +.small-icon-text { + font-size: 17px; } \ No newline at end of file diff --git a/src/themes/OLH/templates/elements/journal/box_article.html b/src/themes/OLH/templates/elements/journal/box_article.html index 65904de074..81b34659c3 100644 --- a/src/themes/OLH/templates/elements/journal/box_article.html +++ b/src/themes/OLH/templates/elements/journal/box_article.html @@ -16,7 +16,7 @@ class="article-thumbnail"> {% endif %}
-

{{ article.title|safe }}

+

{{ article.title|safe }}{% if article.is_remote %} {% endif %}

{% include "elements/journal/authors_block.html" %}

{{ article.date_published|date:"Y-m-d" }} {{ issue.display_title }}

{% for category, articles in structure.items %} -

{{ category }}

- {% for article in articles %} -
-
- -
-
- {% if article.thumbnail_image_file %} - {{ article.title|striptags|escape }} - {% elif request.journal.thumbnail_image %} - - {% else %} - {{ article.title|striptags|escape }} {% endif %} -
-
-

{{ article.title|safe }}

- {% include "elements/journal/authors_block.html" %} -

{{ article.date_published|date:"Y-m-d" }} - {% trans "Volume" %} {{ article.issue.volume }}, - {% trans "Issue" %} {{ article.issue.issue }}

-
-
-
-
+ {% include "elements/journal/box_article.html" with article=article %} {% endfor %} {% endfor %}
diff --git a/src/themes/OLH/templates/journal/search.html b/src/themes/OLH/templates/journal/search.html index 64fb3ff040..44c4154a1c 100644 --- a/src/themes/OLH/templates/journal/search.html +++ b/src/themes/OLH/templates/journal/search.html @@ -15,35 +15,7 @@

{% trans "Articles" %}

{% for article in articles %} -
- -
-
- {% if article.thumbnail_image_file %} - {{ article.title|striptags|escape }} - {% elif request.journal.thumbnail_image %} - - {% else %} - {{ article.title|striptags|escape }} {% endif %} -
-
-

{{ article.title|safe }}

-

{% for author in article.authors.all %}{% if forloop.last %} - {% if article.authors.all|length > 1 %} and - {% endif %}{% endif %}{{ author.full_name }} - {% if not forloop.last %} - {% if not forloop.counter == article.authors.all|length|add:-1 %}, - {% endif %}{% endif %}{% endfor %}

-

{{ article.date_published|date:"Y-m-d" }} {% trans "Volume" %} {{ article.issue.volume }}, - {% trans "Issue" %} {{ article.issue.issue }}

-
-
-
+ {% include "elements/journal/box_article.html" with article=article %} {% endfor %}
diff --git a/src/themes/default/assets/css/bootstrap.css b/src/themes/default/assets/css/bootstrap.css index 4040cf2ceb..cd7328dc24 100644 --- a/src/themes/default/assets/css/bootstrap.css +++ b/src/themes/default/assets/css/bootstrap.css @@ -9608,4 +9608,8 @@ footer svg { a.profilelink:link{ color: #FFFFFF; -} \ No newline at end of file +} + +.small-icon-text { + font-size: 17px !important; +} diff --git a/src/themes/default/templates/elements/article_listing.html b/src/themes/default/templates/elements/article_listing.html index 799ff5a525..1adf947938 100644 --- a/src/themes/default/templates/elements/article_listing.html +++ b/src/themes/default/templates/elements/article_listing.html @@ -17,7 +17,7 @@
-

{{ article.title|safe }}

+

{{ article.title|safe }}{% if article.is_remote %} {% endif %}

{% for author in article.authors.all %}{% if forloop.last %} {% if article.authors.all|length > 1 %} and From fc45dea1318f8178ae3cf46b7cf985ab86388e3d Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Fri, 10 Nov 2017 16:03:00 +0000 Subject: [PATCH 08/34] New journals have a default section "Article". --- src/journal/models.py | 2 +- src/utils/management/commands/install_janeway.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/journal/models.py b/src/journal/models.py index af0c1ceb76..a0ca65eea8 100644 --- a/src/journal/models.py +++ b/src/journal/models.py @@ -56,7 +56,7 @@ def issue_large_image_path(instance, filename): class Journal(models.Model): code = models.CharField(max_length=4) - domain = models.CharField(max_length=255, default='localhost', unique=True) + domain = models.CharField(max_length=255, default='www.example.com', unique=True) current_issue = models.ForeignKey('Issue', related_name='current_issue', null=True, blank=True) carousel = models.OneToOneField('carousel.Carousel', related_name='journal', null=True, blank=True) thumbnail_image = models.ForeignKey('core.File', null=True, blank=True, related_name='thumbnail_image', diff --git a/src/utils/management/commands/install_janeway.py b/src/utils/management/commands/install_janeway.py index b1bea75a4d..27a59731c0 100644 --- a/src/utils/management/commands/install_janeway.py +++ b/src/utils/management/commands/install_janeway.py @@ -5,6 +5,7 @@ from press import models as press_models from journal import models as journal_models from utils import install +from submission import models as submission_models class Command(BaseCommand): @@ -45,6 +46,11 @@ def handle(self, *args, **options): journal.save() journal.setup_directory() + submission_models.Section.objects.get_or_create(journal=journal, + number_of_reviewers=2, + name='Article', + plural='Articles') + print("Thanks, Journal #1 has been saved.\n") call_command('show_configured_journals') From 2d0b8f894d90e416027b818cbfa83dd260be6655 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 13 Nov 2017 11:29:31 +0000 Subject: [PATCH 09/34] Press images can now be non-svg. --- src/core/urls.py | 4 ++-- src/press/templatetags/press_url.py | 9 +++++---- src/press/views.py | 2 +- src/templates/admin/install/index.html | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/core/urls.py b/src/core/urls.py index a2d3b7f2d1..2eb9579bc1 100644 --- a/src/core/urls.py +++ b/src/core/urls.py @@ -65,7 +65,7 @@ url(r'^logout/$', core_views.user_logout, name='core_logout'), url(r'^dashboard/$', core_views.dashboard, name='core_dashboard'), url(r'^dashboard/article/(?P\d+)/$', core_views.dashboard_article, name='core_dashboard_article'), - url(r'^cover/$', press_views.serve_press_cover, name='press_cover_download'), + url(r'^press/cover/$', press_views.serve_press_cover, name='press_cover_download'), # Notes url(r'^article/(?P\d+)/note/(?P\d+)/delete/$', core_views.delete_note, @@ -294,7 +294,7 @@ url(r'^(?P[-\w.]+)/dashboard/$', core_views.dashboard, name='core_dashboard'), url(r'^(?P[-\w.]+)/dashboard/article/(?P\d+)/$', core_views.dashboard_article, name='core_dashboard_article'), - url(r'^(?P[-\w.]+)/cover/$', press_views.serve_press_cover, name='press_cover_download'), + url(r'^(?P[-\w.]+)/press/cover/$', press_views.serve_press_cover, name='press_cover_download'), # Notes url(r'^(?P[-\w.]+)/article/(?P\d+)/note/(?P\d+)/delete/$', diff --git a/src/press/templatetags/press_url.py b/src/press/templatetags/press_url.py index 9c14dc1d70..3863f1ec3f 100644 --- a/src/press/templatetags/press_url.py +++ b/src/press/templatetags/press_url.py @@ -2,9 +2,10 @@ from django import template from django.utils.safestring import mark_safe +from django.urls import reverse +from django.http import Http404 from press import models as press_models - register = template.Library() @@ -18,11 +19,11 @@ def svg(filename): path = filename if not path: - return None + raise Http404 mimetype = mimetypes.guess_type(path, strict=True) if not mimetype or mimetype[0] != 'image/svg+xml': - return None + return mark_safe(''.format(url=reverse('press_cover_download'))) if isinstance(path, (list, tuple)): path = path[0] @@ -31,4 +32,4 @@ def svg(filename): with open(path) as svg_file: return mark_safe(svg_file.read()) except FileNotFoundError: - return None + raise Http404 diff --git a/src/press/views.py b/src/press/views.py index 6fc4704666..485e64cd79 100644 --- a/src/press/views.py +++ b/src/press/views.py @@ -143,7 +143,7 @@ def serve_press_cover(request): """ p = press_models.Press.get_press(request) - response = files.serve_press_cover(request, p) + response = files.serve_press_cover(request, p.thumbnail_image) return response diff --git a/src/templates/admin/install/index.html b/src/templates/admin/install/index.html index 766e433327..c1025d6756 100644 --- a/src/templates/admin/install/index.html +++ b/src/templates/admin/install/index.html @@ -21,7 +21,7 @@

Press

- {% svg request.press_cover %} +
Move to Next Step From 3425a637d99f268333aaa065de83c5bc616cc213 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 13 Nov 2017 15:31:36 +0000 Subject: [PATCH 10/34] Added some css entries. --- src/static/admin/css/admin.css | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/static/admin/css/admin.css b/src/static/admin/css/admin.css index 3b92e154d8..8ef71fc3e7 100644 --- a/src/static/admin/css/admin.css +++ b/src/static/admin/css/admin.css @@ -366,4 +366,17 @@ th { .help-text { margin-bottom: 10px; +} + + +.green { + color: darkgreen; +} + +.red { + color: darkred; +} + +.amber { + color: darkorange; } \ No newline at end of file From c41f61e119c73794040ff99fb296910d16782ff2 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 13 Nov 2017 15:31:55 +0000 Subject: [PATCH 11/34] Added utils stuff for monitoring emails. --- .../management/commands/check_mailgun_stat.py | 64 +++++++++++++++++++ .../migrations/0003_auto_20171113_1251.py | 40 ++++++++++++ src/utils/migrations/0004_logentry_subject.py | 20 ++++++ .../0005_logentry_message_status.py | 20 ++++++ .../migrations/0006_auto_20171113_1444.py | 25 ++++++++ src/utils/models.py | 36 +++++++++-- 6 files changed, 201 insertions(+), 4 deletions(-) create mode 100644 src/utils/management/commands/check_mailgun_stat.py create mode 100644 src/utils/migrations/0003_auto_20171113_1251.py create mode 100644 src/utils/migrations/0004_logentry_subject.py create mode 100644 src/utils/migrations/0005_logentry_message_status.py create mode 100644 src/utils/migrations/0006_auto_20171113_1444.py diff --git a/src/utils/management/commands/check_mailgun_stat.py b/src/utils/management/commands/check_mailgun_stat.py new file mode 100644 index 0000000000..1c6c89ab08 --- /dev/null +++ b/src/utils/management/commands/check_mailgun_stat.py @@ -0,0 +1,64 @@ +import requests +from pprint import pprint + +from django.core.management.base import BaseCommand +from django.conf import settings + +from utils import models + +def get_logs(message_id): + return requests.get( + "https://api.mailgun.net/v3/{0}/events".format(settings.MAILGUN_SERVER_NAME), + auth=("api", settings.MAILGUN_ACCESS_KEY), + params={"message-id" : message_id}) + + +def check_for_perm_failure(event_dict, log): + + for event in event_dict.get('items'): + severity = event.get('severity', None) + if severity == 'permanent': + return True + + return False + + +class Command(BaseCommand): + """Attempts to update mailgun status for log entries""" + + help = "Attempts to update delivery status for mailgun emails." + + def handle(self, *args, **options): + + email_logs = models.LogEntry.objects.filter(is_email=True, + message_id__isnull=False, + status_checks_complete=False) + + for log in email_logs: + logs = get_logs(log.message_id.replace('<', '').replace('>', '')) + event_dict = logs.json() + print('Processing ', log.message_id, '...', end='') + + events = [] + for event in event_dict.get('items'): + events.append(event['event']) + + if 'delivered' in events: + log.message_status = 'delivered' + log.status_checks_complete = True + elif 'failed' in events: + if check_for_perm_failure(event_dict, log): + log.message_status = 'failed' + log.status_checks_complete = True + else: + log.message_status = 'accepted' + + elif 'accepted' in events: + log.message_status = 'accepted' + + log.number_status_checks += 1 + + print(' status {0}'.format(log.message_status)) + + log.save() + diff --git a/src/utils/migrations/0003_auto_20171113_1251.py b/src/utils/migrations/0003_auto_20171113_1251.py new file mode 100644 index 0000000000..e03ec7ca99 --- /dev/null +++ b/src/utils/migrations/0003_auto_20171113_1251.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.5 on 2017-11-13 12:51 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('utils', '0002_auto_20170813_1302'), + ] + + operations = [ + migrations.AddField( + model_name='logentry', + name='is_email', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='logentry', + name='message_id', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='logentry', + name='to', + field=models.EmailField(blank=True, max_length=254, null=True), + ), + migrations.AlterField( + model_name='logentry', + name='types', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AlterField( + model_name='pluginsetting', + name='types', + field=models.CharField(choices=[('rich-text', 'Rich Text'), ('text', 'Text'), ('char', 'Characters'), ('number', 'Number'), ('boolean', 'Boolean'), ('file', 'File'), ('select', 'Select'), ('json', 'JSON')], default='text', max_length=20), + ), + ] diff --git a/src/utils/migrations/0004_logentry_subject.py b/src/utils/migrations/0004_logentry_subject.py new file mode 100644 index 0000000000..57fdfb0ab8 --- /dev/null +++ b/src/utils/migrations/0004_logentry_subject.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.5 on 2017-11-13 14:08 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('utils', '0003_auto_20171113_1251'), + ] + + operations = [ + migrations.AddField( + model_name='logentry', + name='subject', + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/src/utils/migrations/0005_logentry_message_status.py b/src/utils/migrations/0005_logentry_message_status.py new file mode 100644 index 0000000000..e083179c8b --- /dev/null +++ b/src/utils/migrations/0005_logentry_message_status.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.5 on 2017-11-13 14:32 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('utils', '0004_logentry_subject'), + ] + + operations = [ + migrations.AddField( + model_name='logentry', + name='message_status', + field=models.CharField(choices=[('no_information', 'No Information'), ('accepted', 'Accepted'), ('delivered', 'Delivered'), ('failed', 'Failed')], default='no_information', max_length=255), + ), + ] diff --git a/src/utils/migrations/0006_auto_20171113_1444.py b/src/utils/migrations/0006_auto_20171113_1444.py new file mode 100644 index 0000000000..5cd0a2b52d --- /dev/null +++ b/src/utils/migrations/0006_auto_20171113_1444.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.5 on 2017-11-13 14:44 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('utils', '0005_logentry_message_status'), + ] + + operations = [ + migrations.AddField( + model_name='logentry', + name='number_status_checks', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='logentry', + name='status_checks_complete', + field=models.BooleanField(default=False), + ), + ] diff --git a/src/utils/models.py b/src/utils/models.py index 9d9352b9ee..f0dc460bf4 100644 --- a/src/utils/models.py +++ b/src/utils/models.py @@ -35,10 +35,18 @@ ('Info', 'Info'), ] +MESSAGE_STATUS = [ + ('no_information', 'No Information'), + ('accepted', 'Accepted'), + ('delivered', 'Delivered'), + ('failed', 'Failed'), +] + class LogEntry(models.Model): - types = models.CharField(max_length=255, null=True, blank=True, choices=LOG_TYPES) + types = models.CharField(max_length=255, null=True, blank=True) date = models.DateTimeField(auto_now_add=True) + subject = models.TextField(null=True, blank=True) description = models.TextField(null=True, blank=True) level = models.CharField(max_length=20, null=True, blank=True, choices=LOG_LEVELS) actor = models.ForeignKey('core.Account', null=True, blank=True, related_name='actor', on_delete=models.SET_NULL) @@ -48,17 +56,33 @@ class LogEntry(models.Model): object_id = models.PositiveIntegerField(blank=True, null=True) target = GenericForeignKey('content_type', 'object_id') + is_email = models.BooleanField(default=False) + to = models.EmailField(blank=True, null=True) + message_id = models.TextField(blank=True, null=True) + message_status = models.CharField(max_length=255, choices=MESSAGE_STATUS, default='no_information') + number_status_checks = models.IntegerField(default=0) + status_checks_complete = models.BooleanField(default=False) + class Meta: verbose_name_plural = 'log entries' def __str__(self): - return u'[{0}] {1} - {2}'.format(self.types, self.date, self.description) + return u'[{0}] {1} - {2}'.format(self.types, self.date, self.subject) def __repr__(self): - return u'[{0}] {1} - {2}'.format(self.types, self.date, self.description) + return u'[{0}] {1} - {2}'.format(self.types, self.date, self.subject) + + def message_status_class(self): + if self.message_status == 'delivered': + return 'green' + elif self.message_status == 'failed': + return 'red' + else: + return 'amber' @staticmethod - def add_entry(types, description, level, actor=None, request=None, target=None): + def add_entry(types, description, level, actor=None, request=None, target=None, is_email=False, to=None, + message_id=None, subject=None): if actor is not None and callable(getattr(actor, "is_anonymous", None)): if actor.is_anonymous(): @@ -72,6 +96,10 @@ def add_entry(types, description, level, actor=None, request=None, target=None): 'actor': actor if actor else None, 'ip_address': get_ip_address(request), 'target': target, + 'is_email': is_email, + 'to': to, + 'message_id': message_id, + 'subject': subject, } new_entry = LogEntry.objects.create(**kwargs).save() From 5e38b7f9e828db3902854e3bc2b92c880dc93a5c Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 13 Nov 2017 15:32:09 +0000 Subject: [PATCH 12/34] Cron will install the mailgun check systems. --- src/utils/management/commands/install_cron.py | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/utils/management/commands/install_cron.py b/src/utils/management/commands/install_cron.py index 4b4e10d856..a73c0eeb0e 100644 --- a/src/utils/management/commands/install_cron.py +++ b/src/utils/management/commands/install_cron.py @@ -34,20 +34,26 @@ def handle(self, *args, **options): tab = CronTab(user=True) virtualenv = os.environ.get('VIRTUAL_ENV', None) - current_job = find_job(tab, "janeway_cron_job") + jobs = [ + {'name': 'janeway_cron_job', 'time': 10, 'task': 'execute_cron_tasks'}, + {'name': 'janeway_mailgun_job', 'time': 60, 'task': 'check_mailgun_stat'} + ] - if not current_job: - django_command = "{0}/manage.py execute_cron_tasks".format(settings.BASE_DIR) - if virtualenv: - command = '%s/bin/python3 %s' % (virtualenv, django_command) - else: - command = '%s' % (django_command) + for job in jobs: + current_job = find_job(tab, job['name']) - cron_job = tab.new(command, comment="janeway_cron_job") - cron_job.minute.every(10) + if not current_job: + django_command = "{0}/manage.py {1}".format(settings.BASE_DIR, job['task']) + if virtualenv: + command = '%s/bin/python3 %s' % (virtualenv, django_command) + else: + command = '%s' % (django_command) - else: - print("This cron job already exists.") + cron_job = tab.new(command, comment=job['name']) + cron_job.minute.every(job['time']) + + else: + print("{name} cron job already exists.".format(name=job['name'])) if action == 'test': print(tab.render()) From 8ccae9939a2bac28f0555490cf2bce1856c903df Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 13 Nov 2017 15:32:29 +0000 Subject: [PATCH 13/34] Store and display email information. --- src/templates/admin/journal/article_log.html | 15 ++++++--- src/utils/notify_helpers.py | 6 ++-- src/utils/notify_plugins/email_log.py | 35 ++++++++++++++++++++ src/utils/notify_plugins/notify_email.py | 18 ++++++++-- src/utils/transactional_emails.py | 18 +++++----- 5 files changed, 73 insertions(+), 19 deletions(-) create mode 100644 src/utils/notify_plugins/email_log.py diff --git a/src/templates/admin/journal/article_log.html b/src/templates/admin/journal/article_log.html index cd3d2777dc..464ba90c0a 100644 --- a/src/templates/admin/journal/article_log.html +++ b/src/templates/admin/journal/article_log.html @@ -16,17 +16,22 @@

Log Entries

Date Actor Level + Emal Status {% for entry in log_entries %} - {{ entry.types }} - {{ entry.date }} - {{ entry.actor.full_name }} - {{ entry.get_level_display }} - View Content + {{ entry.types }} + {{ entry.date }} + {{ entry.actor.full_name }} + {{ entry.get_level_display }} + + + {{ entry.get_message_status_display }} + + View Content {% endfor %} diff --git a/src/utils/notify_helpers.py b/src/utils/notify_helpers.py index 5c91404dba..2176544de8 100644 --- a/src/utils/notify_helpers.py +++ b/src/utils/notify_helpers.py @@ -16,23 +16,25 @@ def send_slack(request, slack_message, slack_channels): notify.notification(**notify_contents) -def send_email_with_body_from_setting_template(request, template, subject, to, context): +def send_email_with_body_from_setting_template(request, template, subject, to, context, log_dict=None): notify_contents = { 'subject': subject, 'to': to, 'html': render_template.get_message_content(request, context, template), 'action': ['email'], 'request': request, + 'log_dict': log_dict } notify.notification(**notify_contents) -def send_email_with_body_from_user(request, subject, to, body): +def send_email_with_body_from_user(request, subject, to, body, log_dict=None): notify_contents = { 'subject': subject, 'to': to, 'html': body, 'action': ['email'], 'request': request, + 'log_dict': log_dict, } notify.notification(**notify_contents) diff --git a/src/utils/notify_plugins/email_log.py b/src/utils/notify_plugins/email_log.py new file mode 100644 index 0000000000..45dd97baf9 --- /dev/null +++ b/src/utils/notify_plugins/email_log.py @@ -0,0 +1,35 @@ +from utils import models + + +def notify_hook(**kwargs): + # dummy mock-up of new notification hook defer + + # action is a list of notification targets + # if the "all" variable is passed, then some types of notification might act, like Slack. + # Email, though, should only send if it's specifically an email in action, not on "all". + action = kwargs.pop('action', []) + + if 'email_log' not in action: + # email is only sent if list of actions includes "email" + return + + # pop the args + + log_dict = kwargs.pop('log_dict') + + types = log_dict.get('types') + action_text = log_dict.get('action_text') + level = log_dict.get('level') + request = kwargs.pop('request') + target = log_dict.get('target') + response = kwargs.pop('response') + html = kwargs.pop('html') + message_id = response['response'].get('id') + + models.LogEntry.add_entry(types=types, description=html, level=level, + request=request, target=target, is_email=True, to=response.get('to')[0], + message_id=message_id, subject=action_text) + + +def plugin_loaded(): + pass diff --git a/src/utils/notify_plugins/notify_email.py b/src/utils/notify_plugins/notify_email.py index ce5dfa17bb..3bf78e7808 100644 --- a/src/utils/notify_plugins/notify_email.py +++ b/src/utils/notify_plugins/notify_email.py @@ -2,6 +2,7 @@ from django.utils.html import strip_tags from utils import setting_handler +from utils import notify def send_email(subject, to, html, journal, request, bcc=None, cc=None, attachment=None, replyto=None): @@ -39,7 +40,8 @@ def send_email(subject, to, html, journal, request, bcc=None, cc=None, attachmen msg.attach(file.name, file.read(), file.content_type) file.close() - msg.send() + return msg.send() + def notify_hook(**kwargs): @@ -67,9 +69,19 @@ def notify_hook(**kwargs): # call the method if not task: - send_email(subject, to, html, request.journal, request, bcc, cc, attachment) + response = send_email(subject, to, html, request.journal, request, bcc, cc, attachment) else: - send_email(task.email_subject, task.email_to, task.email_html, task.email_journal, request, task.email_bcc, task.email_cc) + response = send_email(task.email_subject, task.email_to, task.email_html, task.email_journal, request, + task.email_bcc, task.email_cc) + + notify_contents = { + 'log_dict': kwargs.pop('log_dict'), + 'request': request, + 'response': response, + 'action': ['email_log'], + 'html': html, + } + notify.notification(**notify_contents) def plugin_loaded(): diff --git a/src/utils/transactional_emails.py b/src/utils/transactional_emails.py index 6247fa957f..b1d9f752fc 100644 --- a/src/utils/transactional_emails.py +++ b/src/utils/transactional_emails.py @@ -377,14 +377,13 @@ def send_copyedit_assignment(**kwargs): copyedit_assignment.due) if not skip: - notify_helpers.send_email_with_body_from_user(request, 'subject_copyeditor_assignment_notification', + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Copyedit Assignment', + 'target': copyedit_assignment.article} + response = notify_helpers.send_email_with_body_from_user(request, 'subject_copyeditor_assignment_notification', copyedit_assignment.copyeditor.email, - user_message_content) + user_message_content, log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Revision Request', description=user_message_content, level='Info', - request=request, target=copyedit_assignment.article) - def send_copyedit_updated(**kwargs): request = kwargs['request'] @@ -420,15 +419,16 @@ def send_copyedit_deleted(**kwargs): 'Copyedit assignment {0} updated'.format(copyedit_assignment.pk), ['slack_editors']) - # send to author + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Copyedit Assignment Deleted', + 'target': copyedit_assignment.article} + # send to copyeditor notify_helpers.send_email_with_body_from_setting_template(request, 'copyedit_deleted', 'subject_copyedit_deleted', copyedit_assignment.copyeditor.email, context={'request': request, - 'copyedit_assignment': copyedit_assignment}) - util_models.LogEntry.add_entry(types='Copyedit Task Deleted', description=description, level='Info', - request=request, target=copyedit_assignment.article) + 'copyedit_assignment': copyedit_assignment}, + log_dict=log_dict) def send_copyedit_decision(**kwargs): From 3b1a910a3fa4fbef173844e6bce16845051a81f4 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 13 Nov 2017 15:52:29 +0000 Subject: [PATCH 14/34] added refresh button to log --- src/journal/views.py | 5 +++++ src/static/admin/js/resolution.js | 2 +- src/templates/admin/journal/article_log.html | 5 ++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/journal/views.py b/src/journal/views.py index 42ff25a4db..8c59a4c095 100644 --- a/src/journal/views.py +++ b/src/journal/views.py @@ -23,6 +23,7 @@ from django.utils.translation import ugettext_lazy as _ from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_POST +from django.core.management import call_command from cms import models as cms_models from core import files, models as core_models, plugin_loader @@ -1187,6 +1188,10 @@ def manage_article_log(request, article_id): content_type = ContentType.objects.get_for_model(article) log_entries = utils_models.LogEntry.objects.filter(content_type=content_type, object_id=article.pk) + if request.POST: + call_command('check_mailgun_stat') + return redirect(reverse('manage_article_log', kwargs={'article_id': article.pk})) + template = 'journal/article_log.html' context = { 'article': article, diff --git a/src/static/admin/js/resolution.js b/src/static/admin/js/resolution.js index a7f1c0696e..b7b3a4a818 100644 --- a/src/static/admin/js/resolution.js +++ b/src/static/admin/js/resolution.js @@ -1,3 +1,3 @@ function run_resolution() { - $('#run').html(' Report Running') + $('#run').html(' Refreshing') } \ No newline at end of file diff --git a/src/templates/admin/journal/article_log.html b/src/templates/admin/journal/article_log.html index 464ba90c0a..c893bb937f 100644 --- a/src/templates/admin/journal/article_log.html +++ b/src/templates/admin/journal/article_log.html @@ -1,4 +1,5 @@ {% extends "admin/core/base.html" %} +{% load static from staticfiles %} {% block title %}Article Log{% endblock %} {% block title-section %}Article Log{% endblock %} @@ -7,6 +8,7 @@

Log Entries

+
{% csrf_token %}
@@ -69,5 +71,6 @@

Article Stage log

{% endblock %} {% block js %} -{% include "elements/datatables.html" with target="#log" sort=1 %} + + {% include "elements/datatables.html" with target="#log" sort=1 %} {% endblock %} \ No newline at end of file From c8f93f0ab6fa2d3451643308a63e57f25899c2a6 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 13 Nov 2017 15:52:39 +0000 Subject: [PATCH 15/34] Chenged display name for accepted to sending. --- src/utils/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/models.py b/src/utils/models.py index f0dc460bf4..cec0d9411c 100644 --- a/src/utils/models.py +++ b/src/utils/models.py @@ -37,7 +37,7 @@ MESSAGE_STATUS = [ ('no_information', 'No Information'), - ('accepted', 'Accepted'), + ('accepted', 'Sending'), ('delivered', 'Delivered'), ('failed', 'Failed'), ] From 8dfe02277ca765cafbe8ea76941b97e39d631193 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 13 Nov 2017 15:52:59 +0000 Subject: [PATCH 16/34] Log now only attempts to store mailgun stuff when response is a dict. --- src/utils/notify_plugins/email_log.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/utils/notify_plugins/email_log.py b/src/utils/notify_plugins/email_log.py index 45dd97baf9..04ca80c9b4 100644 --- a/src/utils/notify_plugins/email_log.py +++ b/src/utils/notify_plugins/email_log.py @@ -22,13 +22,18 @@ def notify_hook(**kwargs): level = log_dict.get('level') request = kwargs.pop('request') target = log_dict.get('target') - response = kwargs.pop('response') html = kwargs.pop('html') - message_id = response['response'].get('id') - models.LogEntry.add_entry(types=types, description=html, level=level, - request=request, target=target, is_email=True, to=response.get('to')[0], - message_id=message_id, subject=action_text) + response = kwargs.pop('response') + + if isinstance(response, dict): + message_id = response['response'].get('id') + models.LogEntry.add_entry(types=types, description=html, level=level, + request=request, target=target, is_email=True, to=response.get('to')[0], + message_id=message_id, subject=action_text) + else: + models.LogEntry.add_entry(types=types, description=html, level=level, + request=request, target=target, subject=action_text) def plugin_loaded(): From 2004ce5810ef15ae108cc4508d74d532e3f4603f Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 13 Nov 2017 20:15:05 +0000 Subject: [PATCH 17/34] Enhanced mailgun features can be enabled or disabled in settings.py --- src/core/example_settings.py | 6 ++++++ src/journal/views.py | 2 +- src/templates/admin/journal/article_log.html | 8 ++++---- src/utils/management/commands/install_cron.py | 4 +++- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/core/example_settings.py b/src/core/example_settings.py index c33eaae62f..49acac2276 100644 --- a/src/core/example_settings.py +++ b/src/core/example_settings.py @@ -310,6 +310,12 @@ def filter(self, record): EMAIL_HOST_PASSWORD = '' EMAIL_USE_TLS = True +# Settings for use with Mailgun +MAILGUN_ACCESS_KEY = '' +MAILGUN_SERVER_NAME = '' +MAILGUN_REQUIRE_TLS = False +ENABLE_ENHANCED_MAILGUN_FEATURES = False # Enables email tracking + DATE_FORMT = "Y-m-d" DATETIME_FORMAT = "Y-m-d H:i" diff --git a/src/journal/views.py b/src/journal/views.py index 8c59a4c095..3a2c72a13e 100644 --- a/src/journal/views.py +++ b/src/journal/views.py @@ -1188,7 +1188,7 @@ def manage_article_log(request, article_id): content_type = ContentType.objects.get_for_model(article) log_entries = utils_models.LogEntry.objects.filter(content_type=content_type, object_id=article.pk) - if request.POST: + if request.POST and settings.ENABLE_ENHANCED_MAILGUN_FEATURES: call_command('check_mailgun_stat') return redirect(reverse('manage_article_log', kwargs={'article_id': article.pk})) diff --git a/src/templates/admin/journal/article_log.html b/src/templates/admin/journal/article_log.html index c893bb937f..fe8d9509fb 100644 --- a/src/templates/admin/journal/article_log.html +++ b/src/templates/admin/journal/article_log.html @@ -8,7 +8,7 @@

Log Entries

-
{% csrf_token %} + {% if settings.ENABLE_ENHANCED_MAILGUN_FEATURES %}
{% csrf_token %}{% endif %}
@@ -18,7 +18,7 @@

Log Entries

- + {% if settings.ENABLE_ENHANCED_MAILGUN_FEATURES %}{% endif %} @@ -29,10 +29,10 @@

Log Entries

- + {% endif %} {% endfor %} diff --git a/src/utils/management/commands/install_cron.py b/src/utils/management/commands/install_cron.py index a73c0eeb0e..cc2e84bf4b 100644 --- a/src/utils/management/commands/install_cron.py +++ b/src/utils/management/commands/install_cron.py @@ -36,9 +36,11 @@ def handle(self, *args, **options): jobs = [ {'name': 'janeway_cron_job', 'time': 10, 'task': 'execute_cron_tasks'}, - {'name': 'janeway_mailgun_job', 'time': 60, 'task': 'check_mailgun_stat'} ] + if settings.ENABLE_ENHANCED_MAILGUN_FEATURES: + jobs.append({'name': 'janeway_mailgun_job', 'time': 60, 'task': 'check_mailgun_stat'}) + for job in jobs: current_job = find_job(tab, job['name']) From e1a0a916605def011de3ea91d8cd57f61c3209ea Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 13 Nov 2017 20:35:05 +0000 Subject: [PATCH 18/34] Update log description modal with status and to fields. --- .../admin/elements/journal/log_description.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/templates/admin/elements/journal/log_description.html b/src/templates/admin/elements/journal/log_description.html index e80b29145a..60461f59f9 100644 --- a/src/templates/admin/elements/journal/log_description.html +++ b/src/templates/admin/elements/journal/log_description.html @@ -9,6 +9,15 @@

 {{ entry.pk }} - {{ entry.types }}

+ {% if settings.ENABLE_ENHANCED_MAILGUN_FEATURES %} +
+

Headers

+
+
+

To: {{ entry.to }}

+

Status: {{ entry.get_message_status_display }}

+
+ {% endif %}

Content

From 35def1dd7bf2eb8d617011aacc82f96be729c2c6 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Tue, 14 Nov 2017 11:16:13 +0000 Subject: [PATCH 19/34] Added subject over-rides for press emails. Closes #219 --- src/core/admin.py | 1 + src/core/logic.py | 12 ++++++++++-- .../admin/elements/journal/log_description.html | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/core/admin.py b/src/core/admin.py index 82d3e5db31..ba2fc85bc5 100644 --- a/src/core/admin.py +++ b/src/core/admin.py @@ -80,6 +80,7 @@ class FileAdmin(admin.ModelAdmin): (models.Country, CountryAdmin), (models.WorkflowElement,), (models.HomepageElement, HomepageElementAdmin), + (models.LoginAttempt,), ] [admin.site.register(*t) for t in admin_list] diff --git a/src/core/logic.py b/src/core/logic.py index b5797b97ae..f5a50ef3cb 100644 --- a/src/core/logic.py +++ b/src/core/logic.py @@ -28,12 +28,17 @@ def send_reset_token(request, reset_token): context = {'reset_token': reset_token} + log_dict = {'level': 'Info', 'types': 'Reset Token', 'target': None} if not request.journal: message = render_template.get_message_content(request, context, request.press.password_reset_text, template_is_setting=True) + subject = 'Password Reset' else: message = render_template.get_message_content(request, context, 'password_reset') - notify_helpers.send_email_with_body_from_user(request, 'subject_password_reset', reset_token.account.email, message) + subject = 'subject_password_reset' + + notify_helpers.send_email_with_body_from_user(request, subject, reset_token.account.email, message, + log_dict=log_dict) def send_confirmation_link(request, new_user): @@ -41,11 +46,14 @@ def send_confirmation_link(request, new_user): if not request.journal: message = render_template.get_message_content(request, context, request.press.registration_text, template_is_setting=True) + subject = 'Registration Confirmation' else: message = render_template.get_message_content(request, context, 'new_user_registration') + subject = 'subject_new_user_registration' notify_helpers.send_slack(request, 'New registration: {0}'.format(new_user.full_name()), ['slack_admins']) - notify_helpers.send_email_with_body_from_user(request, 'subject_new_user_registration', new_user.email, message) + log_dict = {'level': 'Info', 'types': 'Account Confirmation', 'target': None} + notify_helpers.send_email_with_body_from_user(request, subject, new_user.email, message, log_dict=log_dict) def resize_and_crop(img_path, size, crop_type='middle'): diff --git a/src/templates/admin/elements/journal/log_description.html b/src/templates/admin/elements/journal/log_description.html index 60461f59f9..eda9f20c13 100644 --- a/src/templates/admin/elements/journal/log_description.html +++ b/src/templates/admin/elements/journal/log_description.html @@ -9,7 +9,7 @@

 {{ entry.pk }} - {{ entry.types }}

- {% if settings.ENABLE_ENHANCED_MAILGUN_FEATURES %} + {% if settings.ENABLE_ENHANCED_MAILGUN_FEATURES and entry.is_email %}

Headers

From ec1051e906086cd0ddfb479b0a7507692fc7079f Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Tue, 14 Nov 2017 15:24:26 +0000 Subject: [PATCH 20/34] Added a press FK to additional field. --- .../migrations/0017_auto_20171114_1502.py | 27 +++++++++++++++++++ src/submission/models.py | 10 ++++++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/submission/migrations/0017_auto_20171114_1502.py diff --git a/src/submission/migrations/0017_auto_20171114_1502.py b/src/submission/migrations/0017_auto_20171114_1502.py new file mode 100644 index 0000000000..6b380e69e8 --- /dev/null +++ b/src/submission/migrations/0017_auto_20171114_1502.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.5 on 2017-11-14 15:02 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('press', '0012_presssetting_is_boolean'), + ('submission', '0016_auto_20171106_0909'), + ] + + operations = [ + migrations.AddField( + model_name='field', + name='press', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='press.Press'), + ), + migrations.AlterField( + model_name='field', + name='journal', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='journal.Journal'), + ), + ] diff --git a/src/submission/models.py b/src/submission/models.py index 9d170186e9..939b76c8c8 100644 --- a/src/submission/models.py +++ b/src/submission/models.py @@ -1043,7 +1043,8 @@ def width_choices(): class Field(models.Model): - journal = models.ForeignKey('journal.Journal', default=1) + journal = models.ForeignKey('journal.Journal', blank=True, null=True) + press = models.ForeignKey('press.Press', blank=True, null=True) name = models.CharField(max_length=200) kind = models.CharField(max_length=50, choices=field_kind_choices()) width = models.CharField(max_length=50, choices=width_choices(), default='full') @@ -1059,6 +1060,13 @@ class Meta: def __str__(self): return "Field: {0} ({1})".format(self.name, self.kind) + @property + def object(self): + if not self.journal: + return self.press + + return self.journal + class FieldAnswer(models.Model): field = models.ForeignKey(Field, null=True, blank=True, on_delete=models.SET_NULL) From a842511eb255f92fe5d5712a9731c4042d2e780b Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Tue, 14 Nov 2017 15:24:42 +0000 Subject: [PATCH 21/34] Updated additional fields system to handle presses. --- src/submission/forms.py | 1 + src/submission/logic.py | 84 +++++++++++++++++++++++++++++++++++++++++ src/submission/views.py | 25 +++--------- 3 files changed, 90 insertions(+), 20 deletions(-) diff --git a/src/submission/forms.py b/src/submission/forms.py index 3ad4dc81f8..02984f4b2f 100644 --- a/src/submission/forms.py +++ b/src/submission/forms.py @@ -221,6 +221,7 @@ class Meta: model = models.Field exclude = ( 'journal', + 'press', ) diff --git a/src/submission/logic.py b/src/submission/logic.py index a37779f08e..ed1820eb55 100644 --- a/src/submission/logic.py +++ b/src/submission/logic.py @@ -7,6 +7,8 @@ from bs4 import BeautifulSoup from django.db.models import Q +from django.shortcuts import get_object_or_404 +from django.contrib import messages from core import files from core import models as core_models @@ -119,3 +121,85 @@ def import_from_jats_xml(path, journal): article.authors.add(author) return article + + +def get_current_field(request, field_id): + """ + Fetches a field based on whether there is a journal or press in the request object + :param request: HttpRequest + :param field_id: Field PK + :return: Field Object + """ + if field_id: + if request.journal: + field = get_object_or_404(models.Field, pk=field_id, journal=request.journal) + else: + field = get_object_or_404(models.Field, pk=field_id, press=request.press) + else: + field = None + + return field + + +def get_submission_fields(request): + """ + Gets a queryset of fields base on whether there is a journal or press object present in request + :param request: HttpRequest + :return: A queryset of Field objects + """ + + if request.journal: + fields = models.Field.objects.filter(journal=request.journal) + else: + fields = models.Field.objects.filter(press=request.press) + + return fields + + +def save_field(request, form): + """ + Saves a form field and sets the press or journal parameter. + :param request: + :param form: + :return: + """ + + new_field = form.save(commit=False) + + if request.journal: + new_field.journal = request.journal + else: + new_field.press = request.press + + new_field.save() + messages.add_message(request, messages.SUCCESS, 'Field saved.') + return new_field + + +def delete_field(request): + """ + Deletes a field object + :param request: HttpRequest + :return: None, adds a Message obejct to request + """ + + delete_id = request.POST.get('delete') + field_to_delete = get_current_field(request, delete_id) + field_to_delete.delete() + messages.add_message(request, messages.SUCCESS, 'Field deleted. Existing answers will remain intact.') + + +def order_fields(request, fields): + """ + Orders fields from a jquery sortable post. + :param request: HttpRequest + :param fields: Queryset of fields for this object + :return: None + """ + + ids = [int(_id) for _id in request.POST.getlist('order[]')] + + for field in fields: + order = ids.index(field.pk) + field.order = order + field.save() \ No newline at end of file diff --git a/src/submission/views.py b/src/submission/views.py index 1c3337209e..0e2ad9c551 100644 --- a/src/submission/views.py +++ b/src/submission/views.py @@ -498,13 +498,10 @@ def fields(request, field_id=None): :param field_id: Field object PK, optional :return: HttpResponse or HttpRedirect """ - if field_id: - field = get_object_or_404(models.Field, pk=field_id, journal=request.journal) - else: - field = None - fields = models.Field.objects.filter(journal=request.journal) + field = logic.get_current_field(request, field_id) + fields = logic.get_submission_fields(request) form = forms.FieldForm(instance=field) if request.POST: @@ -513,27 +510,15 @@ def fields(request, field_id=None): form = forms.FieldForm(request.POST, instance=field) if form.is_valid(): - new_field = form.save(commit=False) - new_field.journal = request.journal - new_field.save() - messages.add_message(request, messages.SUCCESS, 'Field saved.') + logic.save_field(request, form) return redirect(reverse('submission_fields')) elif 'delete' in request.POST: - delete_id = request.POST.get('delete') - field_to_delete = get_object_or_404(models.Field, pk=delete_id, journal=request.journal) - field_to_delete.delete() - messages.add_message(request, messages.SUCCESS, 'Field deleted. Existing answers will remain intact.') + logic.delete_field(request) return redirect(reverse('submission_fields')) elif 'order[]' in request.POST: - ids = [int(_id) for _id in request.POST.getlist('order[]')] - - for field in fields: - order = ids.index(field.pk) - field.order = order - field.save() - + logic.order_fields(request, fields) return HttpResponse('Thanks') template = 'admin/submission/manager/fields.html' From a01bc291a30b3fb6475e944c08227d49dd5753c0 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Tue, 14 Nov 2017 17:19:01 +0000 Subject: [PATCH 22/34] Added handling of additional fields to preprints. --- src/preprint/forms.py | 57 +++++++++++++++++++ src/preprint/logic.py | 28 ++++++++- src/preprint/views.py | 27 ++------- .../admin/press/press_manager_index.html | 1 + .../OLH/templates/preprints/submit_start.html | 20 +++++++ .../OLH/templates/submission/submit_info.html | 1 - 6 files changed, 111 insertions(+), 23 deletions(-) diff --git a/src/preprint/forms.py b/src/preprint/forms.py index 9b19c50c76..37afd801f0 100644 --- a/src/preprint/forms.py +++ b/src/preprint/forms.py @@ -5,6 +5,7 @@ from submission import models as submission_models from preprint import models from press import models as press_models +from review.forms import render_choices class PreprintInfo(forms.ModelForm): @@ -22,6 +23,7 @@ class Meta: } def __init__(self, *args, **kwargs): + elements = kwargs.pop('additional_fields', None) super(PreprintInfo, self).__init__(*args, **kwargs) self.fields['license'].queryset = submission_models.Licence.objects.filter(press__isnull=False, @@ -34,6 +36,45 @@ def __init__(self, *args, **kwargs): if article: self.fields['subject'].initial = article.get_subject_area() + if elements: + for element in elements: + if element.kind == 'text': + self.fields[element.name] = forms.CharField( + widget=forms.TextInput(attrs={'div_class': element.width}), + required=element.required) + elif element.kind == 'textarea': + self.fields[element.name] = forms.CharField(widget=forms.Textarea, + required=element.required) + elif element.kind == 'date': + self.fields[element.name] = forms.CharField( + widget=forms.DateInput(attrs={'class': 'datepicker', 'div_class': element.width}), + required=element.required) + + elif element.kind == 'select': + choices = render_choices(element.choices) + self.fields[element.name] = forms.ChoiceField( + widget=forms.Select(attrs={'div_class': element.width}), choices=choices, + required=element.required) + + elif element.kind == 'email': + self.fields[element.name] = forms.EmailField( + widget=forms.TextInput(attrs={'div_class': element.width}), + required=element.required) + elif element.kind == 'check': + self.fields[element.name] = forms.BooleanField( + widget=forms.CheckboxInput(attrs={'is_checkbox': True}), + required=element.required) + + self.fields[element.name].help_text = element.help_text + self.fields[element.name].label = element.name + + if article: + try: + check_for_answer = submission_models.FieldAnswer.objects.get(field=element, article=article) + self.fields[element.name].initial = check_for_answer.answer + except submission_models.FieldAnswer.DoesNotExist: + pass + def save(self, commit=True, request=None): article = super(PreprintInfo, self).save() @@ -49,6 +90,22 @@ def save(self, commit=True, request=None): if self.cleaned_data.get('subject', None): article.set_preprint_subject(self.cleaned_data['subject']) + if request: + additional_fields = submission_models.Field.objects.filter(press=request.press) + + for field in additional_fields: + answer = request.POST.get(field.name, None) + print(answer) + if answer: + try: + field_answer = submission_models.FieldAnswer.objects.get(article=article, field=field) + field_answer.answer = answer + field_answer.save() + except submission_models.FieldAnswer.DoesNotExist: + field_answer = submission_models.FieldAnswer.objects.create(article=article, + field=field, + answer=answer) + return article diff --git a/src/preprint/logic.py b/src/preprint/logic.py index 4f85aa70f2..1991bbe640 100644 --- a/src/preprint/logic.py +++ b/src/preprint/logic.py @@ -281,4 +281,30 @@ def unpublish_preprint(request, preprint): preprint.preprint_decision_notification = False preprint.stage = submission_models.STAGE_PREPRINT_REVIEW preprint.save() - messages.add_message(request, messages.INFO, 'This preprint has been unpublished') \ No newline at end of file + messages.add_message(request, messages.INFO, 'This preprint has been unpublished') + + +def get_preprint_article_if_id(request, article_id): + if article_id: + article = get_object_or_404(submission_models.Article.preprints, + pk=article_id, + date_submitted__isnull=True) + else: + article = None + + return article + + +def save_preprint_submit_form(request, form, article, additional_fields): + article = form.save(request=request) + article.owner = request.user + article.is_preprint = True + article.current_step = 1 + article.authors.add(request.user) + article.correspondence_author = request.user + article.save() + + submission_models.ArticleAuthorOrder.objects.get_or_create(article=article, + author=request.user, + defaults={'order': article.next_author_sort()}) + return article \ No newline at end of file diff --git a/src/preprint/views.py b/src/preprint/views.py index 1df55ca3f4..ced4ef0c56 100644 --- a/src/preprint/views.py +++ b/src/preprint/views.py @@ -242,37 +242,22 @@ def preprints_submit(request, article_id=None): :param request: HttpRequest :return: HttpResponse or HttpRedirect """ - if article_id: - article = get_object_or_404(submission_models.Article.preprints, - pk=article_id, - date_submitted__isnull=True) - else: - article = None - - form = forms.PreprintInfo(instance=article) + article = preprint_logic.get_preprint_article_if_id(request, article_id) + additional_fields = submission_models.Field.objects.filter(press=request.press) + form = forms.PreprintInfo(instance=article, additional_fields=additional_fields) if request.POST: - form = forms.PreprintInfo(request.POST, instance=article) + form = forms.PreprintInfo(request.POST, instance=article, additional_fields=additional_fields) if form.is_valid(): - article = form.save() - article.owner = request.user - article.is_preprint = True - article.current_step = 1 - article.authors.add(request.user) - article.correspondence_author = request.user - article.save() - - submission_models.ArticleAuthorOrder.objects.get_or_create(article=article, - author=request.user, - defaults={'order': article.next_author_sort()}) - + article = preprint_logic.save_preprint_submit_form(request, form, article, additional_fields) return redirect(reverse('preprints_authors', kwargs={'article_id': article.pk})) template = 'preprints/submit_start.html' context = { 'form': form, 'article': article, + 'additional_fields': additional_fields, } return render(request, template, context) diff --git a/src/templates/admin/press/press_manager_index.html b/src/templates/admin/press/press_manager_index.html index e3418d1ad6..cc7ab6af85 100644 --- a/src/templates/admin/press/press_manager_index.html +++ b/src/templates/admin/press/press_manager_index.html @@ -28,6 +28,7 @@

Settings

{% if request.press.enable_preprints %} Preprint Settings Preprint Licence Manager + Preprint Additional Fields Manager {% endif %}
diff --git a/src/themes/OLH/templates/preprints/submit_start.html b/src/themes/OLH/templates/preprints/submit_start.html index 1089c4ee46..f3747393f8 100644 --- a/src/themes/OLH/templates/preprints/submit_start.html +++ b/src/themes/OLH/templates/preprints/submit_start.html @@ -2,6 +2,7 @@ {% load static from staticfiles %} {% load i18n %} {% load foundation %} +{% load field %} {% block title %}{% trans "Submit a Preprint" %}{% endblock title %} @@ -72,7 +73,26 @@

{% trans "Submit a Preprint" %}

+ + + + {% if additional_fields %} +
+

+

Additional Fields

+
+ {% for additional_field in additional_fields %} + {% get_form_field form additional_field.name as field %} +
+ {{ field|foundation }} +
+ {% endfor %} + {% endif %} + +
+
+
diff --git a/src/themes/OLH/templates/submission/submit_info.html b/src/themes/OLH/templates/submission/submit_info.html index 5cef7954e1..4a76682d50 100644 --- a/src/themes/OLH/templates/submission/submit_info.html +++ b/src/themes/OLH/templates/submission/submit_info.html @@ -57,7 +57,6 @@

Additional Fields

{{ field|foundation }}
{% endfor %} - {% endif %}
From 3a7f357ca940c13a35c6948b44fef992998ddaf8 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Wed, 15 Nov 2017 12:27:09 +0000 Subject: [PATCH 23/34] Journal Code field is now larger. #220 --- .../migrations/0006_auto_20171115_1216.py | 25 +++++++++++++++++++ src/journal/models.py | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/journal/migrations/0006_auto_20171115_1216.py diff --git a/src/journal/migrations/0006_auto_20171115_1216.py b/src/journal/migrations/0006_auto_20171115_1216.py new file mode 100644 index 0000000000..ede5693d43 --- /dev/null +++ b/src/journal/migrations/0006_auto_20171115_1216.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.5 on 2017-11-15 12:16 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('journal', '0005_auto_20171002_1503'), + ] + + operations = [ + migrations.AlterField( + model_name='journal', + name='code', + field=models.CharField(max_length=10), + ), + migrations.AlterField( + model_name='journal', + name='domain', + field=models.CharField(default='www.example.com', max_length=255, unique=True), + ), + ] diff --git a/src/journal/models.py b/src/journal/models.py index a0ca65eea8..85887dd239 100644 --- a/src/journal/models.py +++ b/src/journal/models.py @@ -55,7 +55,7 @@ def issue_large_image_path(instance, filename): class Journal(models.Model): - code = models.CharField(max_length=4) + code = models.CharField(max_length=10) domain = models.CharField(max_length=255, default='www.example.com', unique=True) current_issue = models.ForeignKey('Issue', related_name='current_issue', null=True, blank=True) carousel = models.OneToOneField('carousel.Carousel', related_name='journal', null=True, blank=True) From eda7ec6a5b9bad3b66d00c4d38d8f582d87f1ef3 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Wed, 15 Nov 2017 12:27:29 +0000 Subject: [PATCH 24/34] We check sites for migrations #220 --- src/utils/management/commands/install_janeway.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/management/commands/install_janeway.py b/src/utils/management/commands/install_janeway.py index 27a59731c0..69620cbbb9 100644 --- a/src/utils/management/commands/install_janeway.py +++ b/src/utils/management/commands/install_janeway.py @@ -22,6 +22,7 @@ def handle(self, *args, **options): :param options: None :return: None """ + call_command('makemigrations', 'sites') call_command('migrate') print("Please answer the following questions.\n") translation.activate('en') From 1cf1d929195c5b9a8c866dbc7ccabea9c75e986a Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Wed, 15 Nov 2017 12:28:07 +0000 Subject: [PATCH 25/34] Fixed hvad bug #220 --- src/utils/management/commands/install_janeway.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/management/commands/install_janeway.py b/src/utils/management/commands/install_janeway.py index 69620cbbb9..d36c75c8dd 100644 --- a/src/utils/management/commands/install_janeway.py +++ b/src/utils/management/commands/install_janeway.py @@ -47,10 +47,10 @@ def handle(self, *args, **options): journal.save() journal.setup_directory() - submission_models.Section.objects.get_or_create(journal=journal, - number_of_reviewers=2, - name='Article', - plural='Articles') + submission_models.Section.objects.language('en').get_or_create(journal=journal, + number_of_reviewers=2, + name='Article', + plural='Articles') print("Thanks, Journal #1 has been saved.\n") From 81d799b184c33388a2bd25c7ad6c53a7f175b60f Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Wed, 15 Nov 2017 12:28:19 +0000 Subject: [PATCH 26/34] Muted sync settings and tidied up the install command. --- .../management/commands/install_janeway.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/utils/management/commands/install_janeway.py b/src/utils/management/commands/install_janeway.py index d36c75c8dd..696b0f4a01 100644 --- a/src/utils/management/commands/install_janeway.py +++ b/src/utils/management/commands/install_janeway.py @@ -4,7 +4,7 @@ from press import models as press_models from journal import models as journal_models -from utils import install +from utils.install import update_settings, update_license from submission import models as submission_models @@ -40,8 +40,16 @@ def handle(self, *args, **options): journal.code = input('Journal #1 code: ') journal.domain = input('Journal #1 domain: ') journal.save() - install.update_settings(journal, management_command=True) - install.update_license(journal, management_command=True) + + print("Installing settings fixtures... ", end="") + update_settings(journal, management_command=False) + print("[okay]") + print("Installing license fixtures... ", end="") + update_license(journal, management_command=False) + print("[okay]") + print("Installing role fixtures") + call_command('loaddata', 'utils/install/roles.json') + journal.name = input('Journal #1 name: ') journal.description = input('Journal #1 description: ') journal.save() @@ -57,10 +65,11 @@ def handle(self, *args, **options): call_command('show_configured_journals') call_command('sync_journals_to_sites') call_command('build_assets') + print("Installing plugins.") call_command('install_plugins') + print("Installing Cron jobs") call_command('install_cron') - call_command('loaddata', 'utils/install/roles.json') print('Create a super user.') call_command('createsuperuser') - print('Open your browser to your domain /install/ to continue this setup process.') + print('Open your browser to your new journal domain {domain)/install/ to continue this setup process.'.format(domain=journal.domain)) From c7d33e1476806809ea897acf5e6f555cb71b642d Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Wed, 15 Nov 2017 12:53:38 +0000 Subject: [PATCH 27/34] Fixed typo. --- src/utils/management/commands/install_janeway.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/management/commands/install_janeway.py b/src/utils/management/commands/install_janeway.py index 696b0f4a01..9f8f93f318 100644 --- a/src/utils/management/commands/install_janeway.py +++ b/src/utils/management/commands/install_janeway.py @@ -72,4 +72,4 @@ def handle(self, *args, **options): print('Create a super user.') call_command('createsuperuser') - print('Open your browser to your new journal domain {domain)/install/ to continue this setup process.'.format(domain=journal.domain)) + print('Open your browser to your new journal domain {domain}/install/ to continue this setup process.'.format(domain=journal.domain)) From 301e3b1716ea2942b8ccc811544cb2b1e48aa84f Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Thu, 16 Nov 2017 12:48:02 +0000 Subject: [PATCH 28/34] Updated example settings for MySQL 5.5+ --- src/core/example_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/example_settings.py b/src/core/example_settings.py index 49acac2276..e752262cee 100644 --- a/src/core/example_settings.py +++ b/src/core/example_settings.py @@ -165,7 +165,7 @@ 'PASSWORD': '', 'HOST': 'localhost', 'PORT': '3306', - 'OPTIONS': {'init_command': 'SET storage_engine=INNODB'}, + 'OPTIONS': {'init_command': 'SET default_storage_engine=INNODB'}, } } From 813b3096b813257e15f4e87c9b61b3f544b5c826 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Thu, 16 Nov 2017 13:08:58 +0000 Subject: [PATCH 29/34] Install links open in new tabs and press details is linked. #220 --- src/templates/admin/install/next.html | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/templates/admin/install/next.html b/src/templates/admin/install/next.html index 35383c7d5b..ab4f1a7737 100644 --- a/src/templates/admin/install/next.html +++ b/src/templates/admin/install/next.html @@ -13,48 +13,54 @@

Next Steps

From 75a15da82310db52763e5c262dc79991a9a97246 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Thu, 16 Nov 2017 14:34:49 +0000 Subject: [PATCH 30/34] Moved default section into Signals block. --- src/journal/models.py | 6 ++++++ src/utils/management/commands/install_janeway.py | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/journal/models.py b/src/journal/models.py index 85887dd239..46db5daf8a 100644 --- a/src/journal/models.py +++ b/src/journal/models.py @@ -513,3 +513,9 @@ def create_sites_folder(sender, instance, created, **kwargs): if created: if not os.path.exists(path): os.makedirs(path) + + from submission.models import Section + Section.objects.language('en').get_or_create(journal=instance, + number_of_reviewers=2, + name='Article', + plural='Articles') diff --git a/src/utils/management/commands/install_janeway.py b/src/utils/management/commands/install_janeway.py index 9f8f93f318..9e1b44a680 100644 --- a/src/utils/management/commands/install_janeway.py +++ b/src/utils/management/commands/install_janeway.py @@ -55,11 +55,6 @@ def handle(self, *args, **options): journal.save() journal.setup_directory() - submission_models.Section.objects.language('en').get_or_create(journal=journal, - number_of_reviewers=2, - name='Article', - plural='Articles') - print("Thanks, Journal #1 has been saved.\n") call_command('show_configured_journals') From 7426ec4553889cbaa17ab225fba623a939f60c57 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Fri, 17 Nov 2017 14:07:20 +0000 Subject: [PATCH 31/34] Typo fixes #264 --- src/preprint/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/preprint/views.py b/src/preprint/views.py index ced4ef0c56..bb4c2f6c85 100644 --- a/src/preprint/views.py +++ b/src/preprint/views.py @@ -531,7 +531,7 @@ def preprints_manager_article(request, article_id): if 'decline' in request.POST: preprint.decline_article() - return redirect(reverse('preprints_notifictation', kwargs={'article_id': preprint.pk})) + return redirect(reverse('preprints_notification', kwargs={'article_id': preprint.pk})) if 'upload' in request.POST: preprint_logic.handle_file_upload(request, preprint) From 4efb20d9f517cc78f9a279f9142555869efa108a Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 20 Nov 2017 10:47:32 +0000 Subject: [PATCH 32/34] Updates to transactional emails. Will need to be merged to 1.2 and 1.2.1 --- src/utils/notify_plugins/email_log.py | 35 ++--- src/utils/transactional_emails.py | 202 ++++++++++++++------------ 2 files changed, 131 insertions(+), 106 deletions(-) diff --git a/src/utils/notify_plugins/email_log.py b/src/utils/notify_plugins/email_log.py index 04ca80c9b4..790d7161b0 100644 --- a/src/utils/notify_plugins/email_log.py +++ b/src/utils/notify_plugins/email_log.py @@ -17,23 +17,24 @@ def notify_hook(**kwargs): log_dict = kwargs.pop('log_dict') - types = log_dict.get('types') - action_text = log_dict.get('action_text') - level = log_dict.get('level') - request = kwargs.pop('request') - target = log_dict.get('target') - html = kwargs.pop('html') - - response = kwargs.pop('response') - - if isinstance(response, dict): - message_id = response['response'].get('id') - models.LogEntry.add_entry(types=types, description=html, level=level, - request=request, target=target, is_email=True, to=response.get('to')[0], - message_id=message_id, subject=action_text) - else: - models.LogEntry.add_entry(types=types, description=html, level=level, - request=request, target=target, subject=action_text) + if log_dict: + types = log_dict.get('types') + action_text = log_dict.get('action_text') + level = log_dict.get('level') + request = kwargs.pop('request') + target = log_dict.get('target') + html = kwargs.pop('html') + + response = kwargs.pop('response') + + if isinstance(response, dict): + message_id = response['response'].get('id') + models.LogEntry.add_entry(types=types, description=html, level=level, + request=request, target=target, is_email=True, to=response.get('to')[0], + message_id=message_id, subject=action_text) + else: + models.LogEntry.add_entry(types=types, description=html, level=level, + request=request, target=target, subject=action_text) def plugin_loaded(): diff --git a/src/utils/transactional_emails.py b/src/utils/transactional_emails.py index b1d9f752fc..5e38bc5644 100644 --- a/src/utils/transactional_emails.py +++ b/src/utils/transactional_emails.py @@ -24,13 +24,12 @@ def send_reviewer_withdrawl_notice(**kwargs): request.user.full_name()) if not skip: + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Review Withdrawl', + 'target': review_assignment.article} notify_helpers.send_email_with_body_from_user(request, 'subject_review_withdrawl', request.user.email, - user_message_content) + user_message_content, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Review Withdrawl Notification', description=description, level='Info', - request=request, target=review_assignment.article) - def send_editor_assigned_acknowledgements_mandatory(**kwargs): """ @@ -61,23 +60,24 @@ def send_editor_assigned_acknowledgements_mandatory(**kwargs): 'editor_assignment': editor_assignment } + log_dict = {'level': 'Info', + 'action_text': description, + 'types': 'Editor Assignment', + 'target': article} + # send to assigned editor if not skip: notify_helpers.send_email_with_body_from_user(request, 'subject_editor_assignment', editor_assignment.editor.email, - user_message_content) - util_models.LogEntry.add_entry(types='Editor Informed of Assignment', description=user_message_content, - level='Info', - request=request, target=article) + user_message_content, log_dict=log_dict) # send to editor if not acknowledgement: notify_helpers.send_slack(request, description, ['slack_editors']) notify_helpers.send_email_with_body_from_setting_template(request, 'editor_assignment', 'subject_editor_assignment', - request.user.email, context) - util_models.LogEntry.add_entry(types='Editor Assigned', description=description, level='Info', request=request, - target=article) + request.user.email, context, + log_dict=log_dict) def send_editor_assigned_acknowledgements(**kwargs): @@ -132,15 +132,16 @@ def send_reviewer_requested_acknowledgements_mandatory(**kwargs): 'review_assignment': review_assignment } + log_dict = {'level': 'Info', + 'action_text': description, + 'types': 'Review Request', + 'target': article} + # send to requested reviewer if not skip: notify_helpers.send_email_with_body_from_user(request, 'subject_review_request_sent', review_assignment.reviewer.email, - user_message_content) - util_models.LogEntry.add_entry(types='Reviewer Notified of Request', description=user_message_content, - level='Info', - request=request, target=article) - + user_message_content, log_dict=log_dict) if not acknowledgement: # send slack notify_helpers.send_slack(request, description, ['slack_editors']) @@ -148,10 +149,8 @@ def send_reviewer_requested_acknowledgements_mandatory(**kwargs): # send to editor notify_helpers.send_email_with_body_from_setting_template(request, 'review_request_sent', 'subject_review_request_sent', - review_assignment.editor.email, context) - - util_models.LogEntry.add_entry(types='Review Request', description=description, level='Info', request=request, - target=article) + review_assignment.editor.email, context, + log_dict=log_dict) def send_review_complete_acknowledgements(**kwargs): @@ -265,6 +264,11 @@ def send_submission_acknowledgement(**kwargs): 'request': request } + log_dict = {'level': 'Info', + 'action_text': 'A new article {0} was submitted'.format(article.title), + 'types': 'New Submission Acknowledgement', + 'target': article} + # send to slack notify_helpers.send_slack(request, 'New submission: {0} {1}'.format(article.title, article.get_remote_url(request)), @@ -275,7 +279,7 @@ def send_submission_acknowledgement(**kwargs): 'submission_acknowledgement', 'subject_submission_acknowledgement', article.correspondence_author.email, - context) + context, log_dict=log_dict) # send to all authors editors_to_email = setting_handler.get_setting( @@ -288,13 +292,11 @@ def send_submission_acknowledgement(**kwargs): else: editor_emails = request.journal.editor_emails - print(editor_emails) - notify_helpers.send_email_with_body_from_setting_template(request, 'editor_new_submission', 'subject_editor_new_submission', editor_emails, - context) + context, log_dict=log_dict) def send_article_decision(**kwargs): @@ -313,14 +315,16 @@ def send_article_decision(**kwargs): decision, request.user.full_name()) + log_dict = {'level': 'Info', + 'action_text': description, + 'types': 'Article Decision', + 'target': article} + if not skip: notify_helpers.send_email_with_body_from_user(request, 'Article Review Decision', request.user.email, - user_message_content) + user_message_content, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Article Decision', description=user_message_content, level='Info', - request=request, target=article) - def send_revisions_request(**kwargs): request = kwargs['request'] @@ -336,15 +340,17 @@ def send_revisions_request(**kwargs): revision.article.title, revision.date_due) + log_dict = {'level': 'Info', + 'action_text': description, + 'types': 'Revision Request', + 'target': revision.article} + if not skip: notify_helpers.send_email_with_body_from_user(request, 'subject_request_revisions', revision.article.correspondence_author.email, - user_message_content) + user_message_content, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Revision Request', description=user_message_content, level='Info', - request=request, target=revision.article) - def send_revisions_complete(**kwargs): request = kwargs['request'] @@ -396,13 +402,19 @@ def send_copyedit_updated(**kwargs): 'Copyedit assignment {0} updated'.format(copyedit_assignment.pk), ['slack_editors']) + log_dict = {'level': 'Info', + 'action_text': 'Copyedit assignment #{number} update.'.format(number=copyedit_assignment.pk), + 'types': 'Revision Request', + 'target': copyedit_assignment.article} + # send to author notify_helpers.send_email_with_body_from_setting_template(request, 'copyedit_updated', 'subject_copyedit_updated', copyedit_assignment.copyeditor.email, context={'request': request, - 'copyedit_assignment': copyedit_assignment}) + 'copyedit_assignment': copyedit_assignment}, + log_dict=log_dict) def send_copyedit_deleted(**kwargs): @@ -440,14 +452,14 @@ def send_copyedit_decision(**kwargs): copyedit_assignment.article.title, copyedit_assignment.due) + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Copyediting Decision', + 'target': copyedit_assignment.article} + notify_helpers.send_email_with_body_from_user(request, 'Article Copyediting Decision', copyedit_assignment.editor.email, - description) + description, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Copyeditor Decision', description=description, level='Info', - request=request, target=copyedit_assignment) - def send_copyedit_author_review(**kwargs): request = kwargs['request'] @@ -461,14 +473,14 @@ def send_copyedit_author_review(**kwargs): copyedit_assignment.article.correspondence_author.full_name()) if not skip: + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Copyedit Author Review', + 'target': copyedit_assignment.article} + notify_helpers.send_email_with_body_from_user(request, 'subject_copyeditor_notify_author', copyedit_assignment.article.correspondence_author.email, - user_message_content) + user_message_content, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Copyedit Author Review', description=user_message_content, level='Info', - request=request, target=copyedit_assignment.article) - def send_copyedit_complete(**kwargs): request = kwargs['request'] @@ -480,14 +492,14 @@ def send_copyedit_complete(**kwargs): copyedit_assignment.copyeditor.full_name(), article.title) + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Copyedit Complete', + 'target': copyedit_assignment.article} + notify_helpers.send_email_with_body_from_user(request, 'subject_copyeditor_notify_editor', copyedit_assignment.editor.email, - description) + description, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Initial Copyedit Complete', description=description, level='Info', - request=request, target=copyedit_assignment) - def send_copyedit_ack(**kwargs): request = kwargs['request'] @@ -499,14 +511,14 @@ def send_copyedit_ack(**kwargs): copyedit_assignment.article.title, ) if not skip: + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Copyedit Acknowledgement', + 'target': copyedit_assignment.article} + notify_helpers.send_email_with_body_from_user(request, 'subject_copyeditor_ack', copyedit_assignment.copyeditor.email, - user_message_content) + user_message_content, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Copyediting Complete', description=user_message_content, level='Info', - request=request, target=copyedit_assignment) - def send_copyedit_reopen(**kwargs): request = kwargs['request'] @@ -519,14 +531,14 @@ def send_copyedit_reopen(**kwargs): copyedit_assignment.copyeditor.full_name()) if not skip: + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Copyedit Complete', + 'target': copyedit_assignment.article} + notify_helpers.send_email_with_body_from_user(request, 'subject_copyeditor_reopen_task', copyedit_assignment.copyeditor.email, - user_message_content) + user_message_content, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Copyediting Reopened', description=user_message_content, level='Info', - request=request, target=copyedit_assignment.article) - def send_typeset_assignment(**kwargs): request = kwargs['request'] @@ -538,14 +550,14 @@ def send_typeset_assignment(**kwargs): typeset_task.assignment.article.title) if not skip: + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Typesetting Assignment', + 'target': typeset_task.assignment.article} + notify_helpers.send_email_with_body_from_user(request, 'subject_typesetter_notification', typeset_task.typesetter.email, - user_message_content) + user_message_content, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Typesetting Assignment', description=user_message_content, level='Info', - request=request, target=typeset_task.assignment.article) - def send_typeset_decision(**kwargs): request = kwargs['request'] @@ -556,14 +568,14 @@ def send_typeset_decision(**kwargs): decision, typeset_task.assignment.article.title) + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Typesetter Decision', + 'target': typeset_task.assignment.article} + notify_helpers.send_email_with_body_from_user(request, 'Article Typesetting Decision', typeset_task.assignment.production_manager.email, - description) + description, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Typesetting Assignment', description=description, level='Info', - request=request, target=typeset_task.assignment.article) - def send_typeset_task_deleted(**kwargs): request = kwargs['request'] @@ -575,16 +587,17 @@ def send_typeset_task_deleted(**kwargs): typeset_task.assignment.article.title, ) + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Typesetter Assignment Deleted', + 'target': typeset_task.assignment.article} + # send to author notify_helpers.send_email_with_body_from_setting_template(request, 'typeset_deleted', 'subject_typeset_deleted', typeset_task.typesetter.email, context={'request': request, - 'typeset_task': typeset_task}) + 'typeset_task': typeset_task}, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Typesetting Assignment Deleted', description=description, level='Info', - request=request, target=typeset_task.assignment.article) def send_typeset_complete(**kwargs): @@ -597,14 +610,14 @@ def send_typeset_complete(**kwargs): typeset_task.note_from_typesetter, ) + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Typesetting Assignment Complete', + 'target': typeset_task.assignment.article} + notify_helpers.send_email_with_body_from_user(request, 'subject_typesetter_complete_notification', typeset_task.assignment.production_manager.email, - description) + description, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Typesetting Assignment', description=description, level='Info', - request=request, target=typeset_task.assignment.article) - def send_production_complete(**kwargs): request = kwargs['request'] @@ -614,6 +627,9 @@ def send_production_complete(**kwargs): description = 'Production has been completed for article {0}.'.format(article.title) + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Production Complete', + 'target': article} + for task in assignment.typesettask_set.all(): notify_helpers.send_email_with_body_from_user(request, 'Article Production Complete', task.typesetter.email, user_content_message) @@ -622,12 +638,10 @@ def send_production_complete(**kwargs): 'production_complete', 'subject_production_complete', article.editor_emails(), - {'article': article, 'assignment': assignment}) + {'article': article, 'assignment': assignment}, + log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Production Complete', description=description, level='Info', - request=request, target=article) - def fire_proofing_manager_assignment(**kwargs): request = kwargs['request'] @@ -638,13 +652,15 @@ def fire_proofing_manager_assignment(**kwargs): proofing_assignment.proofing_manager.full_name(), article.title, ) - + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Proofing Manager Assigned', + 'target': article} context = {'request': request, 'proofing_assignment': proofing_assignment, 'article': article} notify_helpers.send_email_with_body_from_setting_template(request, 'notify_proofing_manager', 'subject_notify_proofing_manager', proofing_assignment.proofing_manager.email, - context) + context, + log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) @@ -659,6 +675,8 @@ def cancel_proofing_task(**kwargs): proofing_task.proofreader.full_name(), request.user.full_name() ) + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Proofing Task Cancelled', + 'target': article} context = {'request': request, 'proofing_task': proofing_task, 'user_content_message': user_content_message} notify_helpers.send_email_with_body_from_setting_template(request, 'notify_proofreader_cancelled', @@ -679,11 +697,13 @@ def edit_proofing_task(**kwargs): request.user.full_name() ) context = {'request': request, 'proofing_task': proofing_task} + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Proofing Task Edited', + 'target': article} notify_helpers.send_email_with_body_from_setting_template(request, 'notify_proofreader_edited', 'subject_notify_proofreader_edited', proofing_task.proofreader.email, - context) + context, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) @@ -698,15 +718,13 @@ def notify_proofreader(**kwargs): proofing_task.proofreader.full_name(), request.user.full_name() ) - + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Proofreading Requested', + 'target': article} notify_helpers.send_email_with_body_from_user(request, 'subject_notify_proofreader_assignment', proofing_task.proofreader.email, - user_content_message) + user_content_message, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - util_models.LogEntry.add_entry(types='Proofreading Requested', description=description, level='Info', - request=request, target=article) - def send_proofreader_decision(**kwargs): request = kwargs['request'] @@ -718,10 +736,11 @@ def send_proofreader_decision(**kwargs): proofing_task.round.assignment.article.title, decision ) - + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Proofreading Update', + 'target': proofing_task.round.assignment.article} notify_helpers.send_email_with_body_from_user(request, 'Article Proofreading Update', proofing_task.round.assignment.proofing_manager.email, - description) + description, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) @@ -754,13 +773,14 @@ def send_proofing_typeset_request(**kwargs): typeset_task.typesetter.full_name(), article.title, ) - + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Typesetting Updates Requested', + 'target': article} if not skip: notify_helpers.send_slack(request, description, ['slack_editors']) notify_helpers.send_email_with_body_from_user( request, 'subject_notify_typesetter_proofing_changes', typeset_task.proofing_task.round.assignment.proofing_manager.email, - user_content_message) + user_content_message, log_dict=log_dict) def send_proofing_typeset_decision(**kwargs): @@ -773,10 +793,11 @@ def send_proofing_typeset_decision(**kwargs): typeset_task.proofing_task.round.assignment.article.title, decision ) - + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Proofing Typesetting', + 'target': typeset_task.assignment.article} notify_helpers.send_email_with_body_from_user(request, 'Proofing Typesetting Changes', typeset_task.proofing_task.round.assignment.proofing_manager.email, - description) + description, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) @@ -790,9 +811,11 @@ def send_corrections_complete(**kwargs): article.title, typeset_task.pk, ) + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Proofing Typesetting Complete', + 'target': typeset_task.assignment.article} notify_helpers.send_email_with_body_from_user(request, 'subject_typesetter_corrections_complete', article.proofingassignment.proofing_manager.email, - description) + description, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) @@ -823,11 +846,12 @@ def send_proofing_complete(**kwargs): skip = kwargs['skip'] description = "Proofing is now complete for {0}".format(article.title) - + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Proofing Complete', + 'target': article} if not skip: notify_helpers.send_email_with_body_from_user(request, 'subject_notify_editor_proofing_complete', article.editor_emails(), - user_message) + user_message, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) From d608e4e737ad0cea12e7fd5a75b1ac910ebafa93 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 20 Nov 2017 15:55:15 +0000 Subject: [PATCH 33/34] Removed sig from submission email. --- src/utils/install/journal_defaults.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/install/journal_defaults.json b/src/utils/install/journal_defaults.json index 6ec826d65a..a69426bce5 100644 --- a/src/utils/install/journal_defaults.json +++ b/src/utils/install/journal_defaults.json @@ -116,7 +116,7 @@ "type": "rich-text" }, "value": { - "default": "Dear {{ article.correspondence_author.full_name }},

Thank you for submitting \"{{ article }}\" to {{ article.journal }}.

Your work will now be reviewed by an editor and we will be in touch as the peer-review process progresses.

Regards,
{{ request.user.signature|safe }}" + "default": "Dear {{ article.correspondence_author.full_name }},

Thank you for submitting \"{{ article }}\" to {{ article.journal }}.

Your work will now be reviewed by an editor and we will be in touch as the peer-review process progresses.

Regards,
" } }, { From d6905dc93381fa8c589c2409ee34b2dc4fbe29a4 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Mon, 20 Nov 2017 16:13:28 +0000 Subject: [PATCH 34/34] Transactional emails now use log_dicts to make log entries. --- src/utils/transactional_emails.py | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/utils/transactional_emails.py b/src/utils/transactional_emails.py index 5e38bc5644..f4032c7ded 100644 --- a/src/utils/transactional_emails.py +++ b/src/utils/transactional_emails.py @@ -866,14 +866,17 @@ def send_author_publication_notification(**kwargs): article.date_published, request.user.full_name()) + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Article Published', + 'target': article} + notify_helpers.send_email_with_body_from_user(request, '{0} Publication'.format(article.title), article.editor_emails(), - user_message) + user_message, log_dict=log_dict) notify_helpers.send_slack(request, description, ['slack_editors']) - # Check for SEs and PRs and notify them as well + # Check for SEs and PRs and notify them as well if section_editors: for editor in article.section_editors(): notify_helpers.send_email_with_body_from_setting_template(request, @@ -896,10 +899,12 @@ def review_sec_override_notification(**kwargs): override = kwargs['override'] description = "{0} overwrote their access to {1}".format(override.editor.full_name(), override.article.title) + log_dict = {'level': 'Warning', 'action_text': description, 'types': 'Security Override', + 'target': override.article} notify_helpers.send_slack(request, description, ['slack_editors']) notify_helpers.send_email_with_body_from_user(request, 'Review Security Override', request.journal.editor_emails, - description) + description, log_dict=log_dict) def send_draft_decison(**kwargs): @@ -913,12 +918,15 @@ def send_draft_decison(**kwargs): description = "Section Editor {0} has drafted a decision for Article {1}".format( draft.section_editor.full_name(), article.title) + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Draft Decision', + 'target': article} notify_helpers.send_slack(request, description, ['slack_editors']) notify_helpers.send_email_with_body_from_setting_template(request, 'draft_editor_message', 'subject_draft_editor_message', emails, - {'draft': draft, 'article': article}) + {'draft': draft, 'article': article}, + log_dict=log_dict) def send_author_copyedit_complete(**kwargs): @@ -949,15 +957,15 @@ def preprint_submission(**kwargs): description = '{author} has submitted a new preprint titled {title}.'.format(author=request.user.full_name(), title=article.title) - - util_models.LogEntry.add_entry('submission', description, 'info', request.user, request, article) + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Submission', + 'target': article} # Send an email to the user context = {'article': article} template = request.press.preprint_submission email_text = render_template.get_message_content(request, context, template, template_is_setting=True) - notify_helpers.send_email_with_body_from_user(request, 'Preprint Submission', request.user.email, email_text) - util_models.LogEntry.add_entry('email', email_text, 'info', request.user, request, article) + notify_helpers.send_email_with_body_from_user(request, 'Preprint Submission', request.user.email, email_text, + log_dict=log_dict) # Send an email to the preprint editor url = request.press_base_url + reverse('preprints_manager_article', kwargs={'article_id': article.pk}) @@ -969,7 +977,6 @@ def preprint_submission(**kwargs): for editor in request.press.preprint_editors(): notify_helpers.send_email_with_body_from_user(request, 'Preprint Submission', editor.email, editor_email_text) - util_models.LogEntry.add_entry('email', editor_email_text, 'info', request.user, request, article) def preprint_publication(**kwargs): @@ -1011,7 +1018,8 @@ def preprint_comment(**kwargs): kwargs={'article_id': article.pk})) description = '{author} commented on {article}'.format(author=request.user.full_name(), article=article.title) + log_dict = {'level': 'Info', 'action_text': description, 'types': 'Preprint Comment', + 'target': article} - util_models.LogEntry.add_entry('comment', description, 'info', request.user, request, article) notify_helpers.send_email_with_body_from_user(request, ' Preprint Comment', article.owner.email, - email_text) + email_text, log_dict=log_dict)
Date Actor LevelEmal StatusEmail Status
{{ entry.date }} {{ entry.actor.full_name }} {{ entry.get_level_display }} + {% if settings.ENABLE_ENHANCED_MAILGUN_FEATURES %} {{ entry.get_message_status_display }} - View Content