From 387f8dca0488db38468a123243b74e8e96e694d0 Mon Sep 17 00:00:00 2001 From: Jorran de Wit <jorrandewit@outlook.com> Date: Tue, 20 Feb 2018 11:39:40 +0100 Subject: [PATCH] Do more --- journals/templatetags/lookup.py | 2 +- mails/forms.py | 142 +---- mails/mixins.py | 152 +++++- .../registration_invitation.html | 4 +- mails/utils.py | 49 +- scipost/models.py | 36 +- .../personal_page/editorial_actions.html | 11 +- scipost/urls.py | 32 +- scipost/utils.py | 491 ------------------ scipost/views.py | 254 --------- submissions/templatetags/lookup.py | 2 +- submissions/views.py | 29 +- 12 files changed, 196 insertions(+), 1008 deletions(-) diff --git a/journals/templatetags/lookup.py b/journals/templatetags/lookup.py index bdfeb24b0..9323d78aa 100644 --- a/journals/templatetags/lookup.py +++ b/journals/templatetags/lookup.py @@ -28,4 +28,4 @@ class PublicationLookup(LookupChannel): Right now only used for draft registration invitations. May be extended in the future for other purposes as well. """ - return request.user.has_perm('can_draft_registration_invitations') + return request.user.has_perm('can_create_registration_invitations') diff --git a/mails/forms.py b/mails/forms.py index dbc6b5959..b69d0d037 100644 --- a/mails/forms.py +++ b/mails/forms.py @@ -1,68 +1,10 @@ -import re -import json -import inspect -from html2text import HTML2Text - from django import forms -from django.core.mail import EmailMultiAlternatives -from django.contrib.auth import get_user_model -from django.conf import settings -from django.template import loader - -from scipost.models import Contributor -# from .mixins import MailUtilsMixin +from .mixins import MailUtilsMixin from .widgets import SummernoteEditor -class MailUtilsMixin: - mail_fields = None - mail_template = '' - - def __init__(self, *args, **kwargs): - self.mail_code = kwargs.pop('mail_code') - self.instance = kwargs.pop('instance', None) - - # Gather meta data - json_location = '%s/mails/templates/mail_templates/%s.json' % (settings.BASE_DIR, - self.mail_code) - try: - self.mail_data = json.loads(open(json_location).read()) - except OSError: - raise NotImplementedError(('You did not create a valid .html and .json file ' - 'for mail_code: %s' % self.mail_code)) - - # Save central object/instance - self.object = self.get_object(**kwargs) - - # Digest the templates - mail_template = loader.get_template('mail_templates/%s.html' % self.mail_code) - if self.instance and self.mail_data.get('context_object'): - kwargs[self.mail_data['context_object']] = self.instance - self.mail_template = mail_template.render(kwargs) - - # Gather Recipients data - self.recipient = '' - if self.object: - recipient = self.object - for attr in self.mail_data.get('to_address').split('.'): - recipient = getattr(recipient, attr) - if inspect.ismethod(recipient): - recipient = recipient() - self.recipient = recipient - super().__init__(*args, **kwargs) - - def get_object(self, **kwargs): - if self.object: - return self.object - if self.instance: - return self.instance - - if self.mail_data.get('context_object'): - return kwargs.get(self.mail_data['context_object'], None) - - -class EmailTemplateForm(MailUtilsMixin, forms.Form): +class EmailTemplateForm(forms.Form, MailUtilsMixin): subject = forms.CharField(max_length=250, label="Subject*") text = forms.CharField(widget=SummernoteEditor, label="Text*") extra_recipient = forms.EmailField(label="Optional: bcc this email to", required=False) @@ -81,7 +23,7 @@ class EmailTemplateForm(MailUtilsMixin, forms.Form): data = None super().__init__(data, *args, **kwargs) - if not self.recipient: + if not self.original_recipient: self.fields['extra_recipient'].label = "Send this email to" self.fields['extra_recipient'].required = True @@ -91,84 +33,26 @@ class EmailTemplateForm(MailUtilsMixin, forms.Form): def save_data(self): # Get text and html - html_message = self.cleaned_data['text'] - handler = HTML2Text() - message = handler.handle(html_message) + self.html_message = self.cleaned_data['text'] + self.subject = self.cleaned_data['subject'] + self.validate_message() # Get recipients list. Try to send through BCC to prevent privacy issues! - bcc_list = [] - if self.mail_data.get('bcc_to', False) and self.object: - if re.match("[^@]+@[^@]+\.[^@]+", self.mail_data.get('bcc_to')): - bcc_list = [self.mail_data.get('bcc_to')] - else: - bcc_to = self.object - for attr in self.mail_data.get('bcc_to').split('.'): - bcc_to = getattr(bcc_to, attr) - - if not isinstance(bcc_to, list): - bcc_list = [bcc_to] - else: - bcc_list = bcc_to - elif re.match("[^@]+@[^@]+\.[^@]+", self.mail_data.get('bcc_to', '')): - bcc_list = [self.mail_data.get('bcc_to')] - - if self.cleaned_data.get('extra_recipient') and self.recipient: - bcc_list.append(self.cleaned_data.get('extra_recipient')) - elif self.cleaned_data.get('extra_recipient') and not self.recipient: - self.recipient = [self.cleaned_data.get('extra_recipient')] - elif not self.recipient: + if self.cleaned_data.get('extra_recipient') and self.original_recipient: + self.bcc_list.append(self.cleaned_data.get('extra_recipient')) + elif self.cleaned_data.get('extra_recipient') and not self.original_recipient: + self.original_recipient = [self.cleaned_data.get('extra_recipient')] + elif not self.original_recipient: self.add_error('extra_recipient', 'Please fill the bcc field to send the mail.') - # Check the send list - if isinstance(self.recipient, list): - recipients = self.recipient - elif not isinstance(self.recipient, str): - try: - recipients = list(self.recipient) - except TypeError: - recipients = [self.recipient] - else: - recipients = [self.recipient] - recipients = list(recipients) - - # Check if email needs to be taken from instance - _recipients = [] - for recipient in recipients: - if isinstance(recipient, Contributor): - _recipients.append(recipient.user.email) - elif isinstance(recipient, get_user_model()): - _recipients.append(recipient.email) - elif isinstance(recipient, str): - _recipients.append(recipient) - - self.mail_fields = { - 'subject': self.cleaned_data['subject'], - 'message': message, - 'html_message': html_message, - 'recipients': _recipients, - 'bcc_list': bcc_list, - } + self.validate_recipients() + self.save_mail_data() def clean(self): data = super().clean() self.save_data() return data - def send(self): - # Send the mail - email = EmailMultiAlternatives( - self.mail_fields['subject'], - self.mail_fields['message'], - '%s <%s>' % (self.mail_data.get('from_address_name', 'SciPost'), - self.mail_data.get('from_address', 'no-reply@scipost.org')), # From - self.mail_fields['recipients'], # To - bcc=self.mail_fields['bcc_list'], - reply_to=[self.mail_data.get('from_address', 'no-reply@scipost.org')]) - email.attach_alternative(self.mail_fields['html_message'], 'text/html') - email.send(fail_silently=False) - if self.object and hasattr(self.object, 'mail_sent'): - self.object.mail_sent() - class HiddenDataForm(forms.Form): def __init__(self, form, *args, **kwargs): diff --git a/mails/mixins.py b/mails/mixins.py index 0d0fd1b8e..029097f24 100644 --- a/mails/mixins.py +++ b/mails/mixins.py @@ -1,6 +1,18 @@ +import re +import json +import inspect +from html2text import HTML2Text + +from django.core.mail import EmailMultiAlternatives from django.contrib import messages +from django.contrib.auth import get_user_model +from django.conf import settings +from django.template import loader + +from scipost.models import Contributor -from .forms import EmailTemplateForm, HiddenDataForm + +from . import forms class MailEditorMixin: @@ -37,15 +49,15 @@ class MailEditorMixin: self.object = self.get_object() form = self.get_form() if form.is_valid(): - self.mail_form = EmailTemplateForm(request.POST or None, - mail_code=self.mail_code, - instance=self.object) + self.mail_form = forms.EmailTemplateForm(request.POST or None, + mail_code=self.mail_code, + instance=self.object) if self.mail_form.is_valid(): return self.form_valid(form) return self.render_to_response( self.get_context_data(form=self.mail_form, - transfer_data_form=HiddenDataForm(form))) + transfer_data_form=forms.HiddenDataForm(form))) else: return self.form_invalid(form) @@ -70,3 +82,133 @@ class MailUtilsMixin: """ This mixin takes care of inserting the default data into the Utils or Form. """ + object = None + mail_fields = {} + mail_template = '' + html_message = '' + message = '' + + def __init__(self, *args, **kwargs): + self.mail_code = kwargs.pop('mail_code') + self.instance = kwargs.pop('instance', None) + + # Gather meta data + json_location = '%s/mails/templates/mail_templates/%s.json' % (settings.BASE_DIR, + self.mail_code) + try: + self.mail_data = json.loads(open(json_location).read()) + except OSError: + raise NotImplementedError(('You did not create a valid .html and .json file ' + 'for mail_code: %s' % self.mail_code)) + + # Save central object/instance + self.object = self.get_object(**kwargs) + + # Digest the templates + mail_template = loader.get_template('mail_templates/%s.html' % self.mail_code) + if self.instance and self.mail_data.get('context_object'): + kwargs[self.mail_data['context_object']] = self.instance + self.mail_template = mail_template.render(kwargs) + + # Gather Recipients data + self.original_recipient = '' + if self.object: + recipient = self.object + for attr in self.mail_data.get('to_address').split('.'): + recipient = getattr(recipient, attr) + if inspect.ismethod(recipient): + recipient = recipient() + self.original_recipient = recipient + + self.subject = self.mail_data['subject'] + + + def validate_recipients(self): + # Get recipients list. Try to send through BCC to prevent privacy issues! + self.bcc_list = [] + if self.mail_data.get('bcc_to', False) and self.object: + if re.match("[^@]+@[^@]+\.[^@]+", self.mail_data.get('bcc_to')): + self.bcc_list = [self.mail_data.get('bcc_to')] + else: + bcc_to = self.object + for attr in self.mail_data.get('bcc_to').split('.'): + bcc_to = getattr(bcc_to, attr) + + if not isinstance(bcc_to, list): + self.bcc_list = [bcc_to] + else: + self.bcc_list = bcc_to + elif re.match("[^@]+@[^@]+\.[^@]+", self.mail_data.get('bcc_to', '')): + self.bcc_list = [self.mail_data.get('bcc_to')] + + # Check the send list + if isinstance(self.original_recipient, list): + recipients = self.original_recipient + elif not isinstance(self.original_recipient, str): + try: + recipients = list(self.original_recipient) + except TypeError: + recipients = [self.original_recipient] + else: + recipients = [self.original_recipient] + recipients = list(recipients) + + # Check if email needs to be taken from an instance + _recipients = [] + for recipient in recipients: + if isinstance(recipient, Contributor): + _recipients.append(recipient.user.email) + elif isinstance(recipient, get_user_model()): + _recipients.append(recipient.email) + elif isinstance(recipient, str): + _recipients.append(recipient) + self.recipients = _recipients + + def validate_message(self): + if not self.html_message: + self.html_message = self.mail_template + handler = HTML2Text() + self.message = handler.handle(self.html_message) + + def validate(self): + """ + Ease workflow by called this wrapper validation method. + + Only to be used when the default data is used, eg. not in the EmailTemplateForm. + """ + self.validate_message() + self.validate_recipients() + self.save_mail_data() + + def save_mail_data(self): + self.mail_fields = { + 'subject': self.subject, + 'message': self.message, + 'html_message': self.html_message, + 'recipients': self.recipients, + 'bcc_list': self.bcc_list, + } + + def get_object(self, **kwargs): + if self.object: + return self.object + if self.instance: + return self.instance + + if self.mail_data.get('context_object'): + return kwargs.get(self.mail_data['context_object'], None) + + def send(self): + # Send the mail + email = EmailMultiAlternatives( + self.mail_fields['subject'], + self.mail_fields['message'], + '%s <%s>' % (self.mail_data.get('from_address_name', 'SciPost'), + self.mail_data.get('from_address', 'no-reply@scipost.org')), # From + self.mail_fields['recipients'], # To + bcc=self.mail_fields['bcc_list'], + reply_to=[self.mail_data.get('from_address', 'no-reply@scipost.org')]) + email.attach_alternative(self.mail_fields['html_message'], 'text/html') + email.send(fail_silently=False) + if self.object and hasattr(self.object, 'mail_sent'): + self.object.mail_sent() diff --git a/mails/templates/mail_templates/registration_invitation.html b/mails/templates/mail_templates/registration_invitation.html index b0b1349ae..fceaa5f99 100644 --- a/mails/templates/mail_templates/registration_invitation.html +++ b/mails/templates/mail_templates/registration_invitation.html @@ -8,7 +8,7 @@ Dear {% if invitation.message_style == 'F' %}{{ invitation.get_title_display }} <br><br> {% if invitation.personal_message %} - {{ personal_message|linebreaks }} + {{ invitation.personal_message|linebreaksbr }} <br> {% endif %} @@ -39,6 +39,7 @@ Dear {% if invitation.message_style == 'F' %}{{ invitation.get_title_display }} </p> {% elif invitation.invitation_type == 'C' %} + {# "Regular" invite #} {% if invitation.citation_notifications.for_publications %} <p> Your work has been cited in @@ -120,6 +121,7 @@ Dear {% if invitation.message_style == 'F' %}{{ invitation.get_title_display }} {{ invitation.invited_by.contributor.get_title_display }} {{ invitation.invited_by.first_name }} {{ invitation.invited_by.last_name }} </p> {% elif invitation.invitation_type == 'F' %} + {# Fellow invite #} <p> You will perhaps have already heard about SciPost, a publication portal established by and for professional scientists. diff --git a/mails/utils.py b/mails/utils.py index 59750638d..ee0d910d6 100644 --- a/mails/utils.py +++ b/mails/utils.py @@ -1,49 +1,14 @@ -from django.core.mail import EmailMultiAlternatives -from django.template import loader +from . import mixins -class DirectMailUtil(object): +class DirectMailUtil(mixins.MailUtilsMixin): """ Same templates and json files as the form EmailTemplateForm, but this will directly send the mails out, without intercepting and showing the mail editor to the user. """ - mail_sender = 'no-reply@scipost.org' - mail_sender_title = '' - @classmethod - def load(cls, _dict, request=None): - cls._context = _dict - cls._context['request'] = request - for var_name in _dict: - setattr(cls, var_name, _dict[var_name]) - - def _send_mail(cls, template_name, recipients, subject, extra_bcc=None, extra_context={}): - """ - Call this method from a classmethod to send emails. - The template will have context variables defined appended from the `load` method. - - Arguments: - template_name -- The .html template to use in the mail. The name be used to get the - following two templates: - `email/<template_name>.txt` (non-HTML) - `email/<template_name>.html` - recipients -- List of mailaddresses to send to mail to. - subject -- The subject of the mail. - """ - template = loader.get_template('email/%s.txt' % template_name) - html_template = loader.get_template('email/%s.html' % template_name) - cls._context.update(extra_context) - message = template.render(cls._context) - html_message = html_template.render(cls._context) - bcc_list = [cls.mail_sender] - if extra_bcc: - bcc_list += extra_bcc - email = EmailMultiAlternatives( - 'SciPost: ' + subject, # message, - message, - '%s <%s>' % (cls.mail_sender_title, cls.mail_sender), - recipients, - bcc=bcc_list, - reply_to=[cls.mail_sender]) - email.attach_alternative(html_message, 'text/html') - email.send(fail_silently=False) + def __init__(self, mail_code, instance, *args, **kwargs): + kwargs['mail_code'] = mail_code + kwargs['instance'] = instance + super().__init__(*args, **kwargs) + self.validate() diff --git a/scipost/models.py b/scipost/models.py index 3f6779ee9..46e448359 100644 --- a/scipost/models.py +++ b/scipost/models.py @@ -189,7 +189,7 @@ class DraftInvitation(models.Model): class RegistrationInvitation(models.Model): """ - Invitation to particular persons for registration + Deprecated: Use the `invitations` app """ title = models.CharField(max_length=4, choices=TITLE_CHOICES) first_name = models.CharField(max_length=30) @@ -218,29 +218,11 @@ class RegistrationInvitation(models.Model): responded = models.BooleanField(default=False) declined = models.BooleanField(default=False) - # objects = RegistrationInvitationManager() - # - # class Meta: - # ordering = ['last_name'] - # - # def __str__(self): - # return (self.first_name + ' ' + self.last_name - # + ' on ' + self.date_sent.strftime("%Y-%m-%d")) - # - # def refresh_keys(self, force_new_key=False): - # # Generate email activation key and link - # if not self.invitation_key or force_new_key: - # salt = "" - # for i in range(5): - # salt = salt + random.choice(string.ascii_letters) - # salt = salt.encode('utf8') - # invitationsalt = self.last_name.encode('utf8') - # self.invitation_key = hashlib.sha1(salt + invitationsalt).hexdigest() - # self.key_expires = timezone.now() + datetime.timedelta(days=365) - # self.save() - class CitationNotification(models.Model): + """ + Deprecated: Use the `invitations` app + """ contributor = models.ForeignKey('scipost.Contributor', on_delete=models.CASCADE) cited_in_submission = models.ForeignKey('submissions.Submission', on_delete=models.CASCADE, @@ -250,16 +232,6 @@ class CitationNotification(models.Model): blank=True, null=True) processed = models.BooleanField(default=False) - # def __str__(self): - # text = str(self.contributor) + ', cited in ' - # if self.cited_in_submission: - # text += self.cited_in_submission.arxiv_identifier_w_vn_nr - # elif self.cited_in_publication: - # text += self.cited_in_publication.citation() - # if self.processed: - # text += ' (processed)' - # return text - class AuthorshipClaim(models.Model): claimant = models.ForeignKey('scipost.Contributor', diff --git a/scipost/templates/partials/scipost/personal_page/editorial_actions.html b/scipost/templates/partials/scipost/personal_page/editorial_actions.html index 10fefa062..0996ec371 100644 --- a/scipost/templates/partials/scipost/personal_page/editorial_actions.html +++ b/scipost/templates/partials/scipost/personal_page/editorial_actions.html @@ -10,7 +10,7 @@ </div> <div class="row"> - {% if perms.scipost.can_vet_registration_requests or perms.scipost.can_draft_registration_invitations or perms.scipost.can_manage_registration_invitations %} + {% if perms.scipost.can_vet_registration_requests or perms.scipost.can_create_registration_invitations or perms.scipost.can_resend_registration_requests %} <div class="col-md-4"> <h3>Registration actions</h3> <ul> @@ -20,20 +20,15 @@ {% if perms.scipost.can_resend_registration_requests %} <li><a href="{% url 'scipost:registration_requests' %}">Awaiting validation</a> ({{ nr_reg_awaiting_validation }})</li> {% endif %} - {% if perms.scipost.can_draft_registration_invitations %} - <li><a href="{% url 'scipost:contributors_filter' %}">Contributors filter</a></li> - <li><a href="{% url 'scipost:draft_registration_invitation' %}">Draft a Registration Invitation</a></li> + {% if perms.scipost.can_create_registration_invitations %} <li><a href="{% url 'invitations:list' %}">Manage Registration Invitations</a></li> {% endif %} - {% if perms.scipost.can_manage_registration_invitations %} - <li><a href="{% url 'scipost:registration_invitations' %}">Manage Registration Invitations</a></li> - {% endif %} </ul> {% if perms.scipost.can_manage_registration_invitations %} <h3>Notifications</h3> <ul> - <li><a href="{% url 'scipost:citation_notifications' %}">Manage citation notifications</a></li> + <li><a href="{% url 'invitations:citation_notification_list' %}">Manage citation notifications</a></li> </ul> {% endif %} diff --git a/scipost/urls.py b/scipost/urls.py index 421a4e2bc..9da0a19f2 100644 --- a/scipost/urls.py +++ b/scipost/urls.py @@ -84,38 +84,8 @@ urlpatterns = [ url(r'^registration_requests/(?P<contributor_id>[0-9]+)/reset$', views.registration_requests_reset, name="registration_requests_reset"), - # # Invitations - # url(r'^registration_invitations$', - # views.registration_invitation_list, name="registration_invitations"), - # url(r'^registration_invitations/(?P<invitation_id>[0-9]+)/renew$', - # views.renew_registration_invitation, name="renew_registration_invitation"), - # url(r'^registration_invitations/(?P<draft_id>[0-9]+)$', - # views.registration_invitations_form, name="registration_invitations_from_draft"), - # url(r'^registration_invitations/cleanup$', views.registration_invitations_cleanup, - # name="registration_invitations_cleanup"), - # url(r'^registration_invitations/(?P<invitation_id>[0-9]+)/remove$', - # views.remove_registration_invitation, name="remove_registration_invitation"), - # url(r'^registration_invitations/(?P<invitation_id>[0-9]+)/mark_declined$', - # views.registration_invitation_mark_declined, - # name="registration_invitation_mark_declined"), - # - # # Draft Invitations - # url(r'^registration_invitations/drafts$', - # views.draft_registration_invitation, name="draft_registration_invitation"), - # url(r'^registration_invitations/drafts/(?P<draft_id>[0-9]+)$', - # views.draft_registration_invitation_form, name="draft_registration_invitation_form"), - # url(r'^registration_invitations/drafts/(?P<draft_id>[0-9]+)/map_to_contributor/(?P<contributor_id>[0-9]+)$', - # views.map_draft_reg_inv_to_contributor, name="map_draft_reg_inv_to_contributor"), - # url(r'^registration_invitations/drafts/(?P<draft_id>[0-9]+)/mark_processed$', - # views.draft_registration_invitation_processed, name='mark_draft_inv_as_processed'), - # url(r'^contributors_filter$', views.contributors_filter, name="contributors_filter"), - - # Registration invitations + # Registration invitations (Never change this route! Thank you.) url(r'^invitation/(?P<key>.+)$', views.invitation, name='invitation'), - # url(r'^citation_notifications$', - # views.citation_notifications, name='citation_notifications'), - # url(r'^process_citation_notification/(?P<cn_id>[0-9]+)$', - # views.process_citation_notification, name='process_citation_notification'), # Authentication url(r'^login/$', views.login_view, name='login'), diff --git a/scipost/utils.py b/scipost/utils.py index 350d1eabe..de045624e 100644 --- a/scipost/utils.py +++ b/scipost/utils.py @@ -1,17 +1,3 @@ -import datetime -import hashlib -import random -import string - -from django.contrib.auth.models import User - -from django.core.mail import EmailMultiAlternatives -from django.core.urlresolvers import reverse -from django.template import Context, Template -from django.utils import timezone - -from .models import DraftInvitation, RegistrationInvitation - from common.utils import BaseMailUtil @@ -106,480 +92,3 @@ class Utils(BaseMailUtil): cls._send_mail(cls, 'new_activation_link', [cls._context['contributor'].user.email], 'new email activation link') - - # @classmethod - # def send_registration_invitation_email(cls, renew=False): - # signature = (cls.invitation.invited_by.get_title_display() + ' ' - # + cls.invitation.invited_by.user.first_name + ' ' - # + cls.invitation.invited_by.user.last_name) - # if not renew: - # # Generate email activation key and link - # salt = "" - # for i in range(5): - # salt = salt + random.choice(string.ascii_letters) - # salt = salt.encode('utf8') - # invitationsalt = cls.invitation.last_name - # invitationsalt = invitationsalt.encode('utf8') - # cls.invitation.invitation_key = hashlib.sha1(salt+invitationsalt).hexdigest() - # cls.invitation.key_expires = datetime.datetime.strftime( - # datetime.datetime.now() + datetime.timedelta(days=365), "%Y-%m-%d %H:%M:%S") - # if renew: - # cls.invitation.nr_reminders += 1 - # cls.invitation.date_last_reminded = timezone.now() - # cls.invitation.save() - # email_text = '' - # email_text_html = '' - # email_context = {} - # if renew: - # email_text += ('Reminder: Invitation to SciPost\n' - # '-------------------------------\n\n') - # email_text_html += ('<strong>Reminder: Invitation to SciPost</strong>' - # '<br/><hr/><br/>') - # if cls.invitation.invitation_type == 'F': - # email_text += 'RE: Invitation to join the Editorial College of SciPost\n\n' - # email_text_html += ('<strong>RE: Invitation to join the Editorial College ' - # 'of SciPost</strong><br/><hr/><br/>') - # email_text += 'Dear ' - # email_text_html += 'Dear ' - # if cls.invitation.message_style == 'F': - # email_text += cls.invitation.get_title_display() + ' ' + cls.invitation.last_name - # email_text_html += '{{ title }} {{ last_name }}' - # email_context['title'] = cls.invitation.get_title_display() - # email_context['last_name'] = cls.invitation.last_name - # else: - # email_text += cls.invitation.first_name - # email_text_html += '{{ first_name }}' - # email_context['first_name'] = cls.invitation.first_name - # email_text += ',\n\n' - # email_text_html += ',<br/>' - # if len(cls.invitation.personal_message) > 3: - # email_text += cls.invitation.personal_message + '\n\n' - # email_text_html += '\n{{ personal_message|linebreaks }}<br/>\n' - # email_context['personal_message'] = cls.invitation.personal_message - # - # # This text to be put in C, ci invitations - # summary_text = ( - # '\n\nIn summary, SciPost.org is a publication portal managed by ' - # 'professional scientists, offering (among others) high-quality ' - # 'Open Access journals with innovative forms of refereeing, and a ' - # 'means of commenting on all existing literature. SciPost is established as ' - # 'a not-for-profit foundation devoted to serving the interests of the ' - # 'international scientific community.' - # '\n\nThe site is anchored at https://scipost.org. Many further details ' - # 'about SciPost, its principles, ideals and implementation can be found at ' - # 'https://scipost.org/about and https://scipost.org/FAQ.' - # '\n\nAs a professional academic, you can register at ' - # 'https://scipost.org/register, enabling you to contribute to the site\'s ' - # 'contents, for example by offering submissions, reports and comments.' - # '\n\nFor your convenience, a partly pre-filled registration ' - # 'form has been prepared for you at ' - # 'https://scipost.org/invitation/' + cls.invitation.invitation_key - # + ' (you can in any case still register at ' - # 'https://scipost.org/register).\n\n' - # 'If you do develop sympathy for the initiative, besides participating in the ' - # 'online platform, we would be very grateful if you considered submitting a ' - # 'publication to one of the journals within the near future, in order to help ' - # 'establish their reputation. We\'ll also be looking forward to your reaction, ' - # 'comments and suggestions about the initiative, which we hope you will find ' - # 'useful to your work as a professional scientist.' - # '\n\nMany thanks in advance for taking a few minutes to look into it,' - # '\n\nOn behalf of the SciPost Foundation,\n\n' - # + signature + '\n' - # ) - # - # summary_text_html = ( - # '\n<p>In summary, SciPost.org is a publication portal managed by ' - # 'professional scientists, offering (among others) high-quality ' - # 'Open Access journals with innovative forms of refereeing, and a ' - # 'means of commenting on all existing literature. SciPost is established as ' - # 'a not-for-profit foundation devoted to serving the interests of the ' - # 'international scientific community.</p>' - # '\n<p>The site is anchored at <a href="https://scipost.org">scipost.org</a>. ' - # 'Many further details ' - # 'about SciPost, its principles, ideals and implementation can be found at ' - # 'the <a href="https://scipost.org/about">about</a> ' - # 'and <a href="https://scipost.org/FAQ">FAQ</a> pages.</p>' - # '<p>As a professional academic, you can register at the ' - # '<a href="https://scipost.org/register">registration page</a>, ' - # 'enabling you to contribute to the site\'s ' - # 'contents, for example by offering submissions, reports and comments.</p>' - # '\n<p>For your convenience, a partly pre-filled ' - # '<a href="https://scipost.org/invitation/{{ invitation_key }}">registration form</a>' - # ' has been prepared for you (you can in any case still register at the ' - # '<a href="https://scipost.org/register">registration page</a>).</p>' - # '\n<p>If you do develop sympathy for the initiative, besides participating in the ' - # 'online platform, we would be very grateful if you considered submitting a ' - # 'publication to one of the journals within the near future, in order to help ' - # 'establish their reputation. We\'ll also be looking forward to your reaction, ' - # 'comments and suggestions about the initiative, which we hope you will find ' - # 'useful to your work as a professional scientist.</p>' - # '\n<p>Many thanks in advance for taking a few minutes to look into it,</p>' - # '<p>On behalf of the SciPost Foundation,</p>' - # '<p>' + signature + '</p>' - # ) - # email_context['invitation_key'] = cls.invitation.invitation_key - # - # if cls.invitation.invitation_type == 'R': - # # Refereeing invitation - # # Details of the submission to referee are already in the personal_message field - # email_text += ( - # 'We would hereby like to cordially invite you ' - # 'to become a Contributor on SciPost ' - # '(this is required in order to deliver reports; ' - # 'our records show that you are not yet registered); ' - # 'for your convenience, we have prepared a pre-filled form for you at\n\n' - # 'https://scipost.org/invitation/' + cls.invitation.invitation_key + '\n\n' - # 'after which your registration will be activated, allowing you to contribute, ' - # 'in particular by providing referee reports.\n\n' - # 'To ensure timely processing of the submission (out of respect for the authors), ' - # 'we would appreciate a quick accept/decline ' - # 'response from you, ideally within the next 2 days.\n\n' - # 'If you are not able to provide a Report, you can let us know by simply ' - # 'navigating to \n\nhttps://scipost.org/submissions/decline_ref_invitation/' - # + cls.invitation.invitation_key + '\n\n' - # 'If you are able to provide a Report, you can confirm this after registering ' - # 'and logging in (you will automatically be prompted for a confirmation).\n\n' - # 'We very much hope that we can count on your expertise,\n\n' - # 'Many thanks in advance,\n\nThe SciPost Team') - # email_text_html += ( - # '\n<p>We would hereby like to cordially invite you ' - # 'to become a Contributor on SciPost ' - # '(this is required in order to deliver reports; ' - # 'our records show that you are not yet registered); ' - # 'for your convenience, we have prepared a pre-filled ' - # '<a href="https://scipost.org/invitation/{{ invitation_key }}">registration form</a> ' - # 'for you. After activation of your registration, you will be allowed to contribute, ' - # 'in particular by providing referee reports.</p>' - # '<p>To ensure timely processing of the submission (out of respect for the authors), ' - # 'we would appreciate a quick accept/decline ' - # 'response from you, ideally within the next 2 days.</p>' - # '<p>If you are <strong>not</strong> able to provide a Report, ' - # 'you can let us know by simply ' - # '<a href="https://scipost.org/submissions/decline_ref_invitation/{{ invitation_key }}">' - # 'clicking here</a>.</p>' - # '<p>If you are able to provide a Report, you can confirm this after registering ' - # 'and logging in (you will automatically be prompted for a confirmation).</p>' - # '<p>We very much hope that we can count on your expertise,</p>' - # '<p>Many thanks in advance,</p>' - # '<p>The SciPost Team</p>') - # - # email_text += SCIPOST_SUMMARY_FOOTER - # email_text_html += SCIPOST_SUMMARY_FOOTER_HTML - # email_text_html += '<br/>' + EMAIL_FOOTER - # html_template = Template(email_text_html) - # html_version = html_template.render(Context(email_context)) - # emailmessage = EmailMultiAlternatives( - # 'SciPost: refereeing request (and registration invitation)', email_text, - # 'SciPost Refereeing <refereeing@scipost.org>', - # [cls.invitation.email], - # cc=[cls.invitation.invited_by.user.email], - # bcc=['refereeing@scipost.org'], - # reply_to=['refereeing@scipost.org']) - # emailmessage.attach_alternative(html_version, 'text/html') - # - # elif cls.invitation.invitation_type == 'ci': - # # Has been cited in a Submission. Invite! - # email_text += ( - # 'Your work has been cited in a manuscript submitted to SciPost,' - # '\n\n' + cls.invitation.cited_in_submission.title - # + ' by ' + cls.invitation.cited_in_submission.author_list + '.\n\n' - # 'I would hereby like to use this opportunity to quickly introduce ' - # 'you to the SciPost initiative, and to invite you to become an active ' - # 'Contributor to the site. You might for example consider reporting or ' - # 'commenting on the above submission before the refereeing deadline.') - # email_text_html += ( - # '<p>Your work has been cited in a manuscript submitted to SciPost,</p>' - # '<p>{{ sub_title }} <br>by {{ sub_author_list }},</p>' - # '<p>which you can find online at the ' - # '<a href="https://scipost.org/submission/{{ arxiv_nr_w_vn_nr }}">' - # 'submission\'s page</a>.</p>' - # '\n<p>I would hereby like to use this opportunity to quickly introduce ' - # 'you to the SciPost initiative, and to invite you to become an active ' - # 'Contributor to the site. You might for example consider reporting or ' - # 'commenting on the above submission before the refereeing deadline.</p>') - # email_context['sub_title'] = cls.invitation.cited_in_submission.title - # email_context['sub_author_list'] = cls.invitation.cited_in_submission.author_list - # email_context['arxiv_identifier_w_vn_nr'] = cls.invitation.cited_in_submission.arxiv_identifier_w_vn_nr - # - # email_text += summary_text - # email_text_html += summary_text_html - # email_text_html += '<br/>' + EMAIL_FOOTER - # html_template = Template(email_text_html) - # html_version = html_template.render(Context(email_context)) - # emailmessage = EmailMultiAlternatives( - # 'SciPost: invitation', email_text, - # 'SciPost registration <registration@scipost.org>', - # [cls.invitation.email], - # cc=[cls.invitation.invited_by.user.email], - # bcc=['registration@scipost.org'], - # reply_to=['registration@scipost.org']) - # emailmessage.attach_alternative(html_version, 'text/html') - # - # elif cls.invitation.invitation_type == 'cp': - # # Has been cited in a Publication. Invite! - # email_text += ( - # 'Your work has been cited in a paper published by SciPost,' - # '\n\n' + cls.invitation.cited_in_publication.title - # + '\nby ' + cls.invitation.cited_in_publication.author_list + - # '\n\n(published as ' + cls.invitation.cited_in_publication.citation() - # + ').\n\n' - # 'I would hereby like to use this opportunity to quickly introduce ' - # 'you to the SciPost initiative, and to invite you to become an active ' - # 'Contributor to the site.') - # email_text_html += ( - # '<p>Your work has been cited in a paper published by SciPost,</p>' - # '<p>{{ pub_title }}</p> <p>by {{ pub_author_list }}</p>' - # '(published as <a href="https://scipost.org/{{ doi_label }}">{{ citation }}</a>).' - # '</p>' - # '\n<p>I would hereby like to use this opportunity to quickly introduce ' - # 'you to the SciPost initiative, and to invite you to become an active ' - # 'Contributor to the site.</p>') - # email_context['pub_title'] = cls.invitation.cited_in_publication.title - # email_context['pub_author_list'] = cls.invitation.cited_in_publication.author_list - # email_context['doi_label'] = cls.invitation.cited_in_publication.doi_label - # email_context['citation'] = cls.invitation.cited_in_publication.citation() - # email_text += summary_text - # email_text_html += summary_text_html - # email_text_html += '<br/>' + EMAIL_FOOTER - # html_template = Template(email_text_html) - # html_version = html_template.render(Context(email_context)) - # emailmessage = EmailMultiAlternatives( - # 'SciPost: invitation', email_text, - # 'SciPost registration <registration@scipost.org>', - # [cls.invitation.email], - # cc=[cls.invitation.invited_by.user.email], - # bcc=['registration@scipost.org'], - # reply_to=['registration@scipost.org']) - # emailmessage.attach_alternative(html_version, 'text/html') - # - # elif cls.invitation.invitation_type == 'C': - # email_text += ('I would hereby like to quickly introduce ' - # 'you to a scientific publishing initiative ' - # 'called SciPost, and to invite you to become an active Contributor.') - # email_text += summary_text - # email_text_html += ( - # '<p>I would hereby like to quickly introduce ' - # 'you to a scientific publishing initiative ' - # 'called SciPost, and to invite you to become an active Contributor.</p>') - # email_text_html += summary_text_html + '<br/>' + EMAIL_FOOTER - # html_template = Template(email_text_html) - # html_version = html_template.render(Context(email_context)) - # emailmessage = EmailMultiAlternatives( - # 'SciPost: invitation', email_text, - # 'SciPost registration <registration@scipost.org>', - # [cls.invitation.email], - # cc=[cls.invitation.invited_by.user.email], - # bcc=['registration@scipost.org'], - # reply_to=['registration@scipost.org']) - # emailmessage.attach_alternative(html_version, 'text/html') - # - # elif cls.invitation.invitation_type == 'F': - # email_text += ( - # '\nYou will perhaps have already heard about SciPost, a publication ' - # 'portal established by and for professional scientists.\n' - # '\nSciPost.org is legally based on a not-for-profit foundation and will ' - # 'operate in perpetuity as a non-commercial entity at the exclusive service ' - # 'of the academic sector, bringing a cost-slashing alternative to existing ' - # 'practices.\n' - # '\nSciPost offers a collection of two-way open ' - # 'access (no subscription fees, no author fees) journals with extremely ' - # 'stringent (peer-witnessed) refereeing, overseen by ' - # 'our Editorial College (exclusively composed ' - # 'of established, professionally practising scientists). The whole process is ' - # 'designed to ensure the highest achievable scientific quality while making the ' - # 'editorial workflow as light and efficient as possible.\n' - # '\nTo go straight to the point, on behalf of the foundation ' - # 'and in view of your professional expertise, I hereby would ' - # 'like to invite you to become an Editorial Fellow and thus join the ' - # 'Editorial College of SciPost Physics.\n\n' - # 'Please note that only well-known and respected senior academics are ' - # 'being contacted for this purpose. Academic reputation and involvement ' - # 'in the community are the most important criteria guiding our ' - # 'considerations of who should belong to the Editorial College.\n' - # '\nTo help you in considering this, it would be best if you were to take ' - # 'the time to look at the website itself, which is anchored at scipost.org. ' - # 'Besides looking around the side, you can also personally register ' - # '(to become a Contributor, without necessarily committing to membership ' - # 'of the Editorial College, this to be discussed separately) by visiting ' - # 'the following single-use link, containing a partly pre-filled form for ' - # 'your convenience: \n\n' - # 'https://scipost.org/invitation/' + cls.invitation.invitation_key + '.\n' - # '\nMany details about the initiative ' - # 'can then be found at scipost.org/about and at scipost.org/FAQ. ' - # 'Functioning of the College will proceed according to the by-laws set ' - # 'out in scipost.org/EdCol_by-laws.\n\n' - # 'Since the success of this initiative is dependent on the involvement of ' - # 'the very people it is meant to serve, we\'d be very grateful if you were ' - # 'to give due consideration to this proposal. We would expect you to ' - # 'commit just 2-4 hours per month to help perform Editorial duties; we will ' - # 'adjust the number of Editorial Fellows to ensure this is the case. You ' - # 'could try it out for 6 months or a year, and of course you could quit ' - # 'any time you wished.\n\n' - # 'I\'d be happy to provide you with more information, should you require ' - # 'it. In view of our development plans, I would be grateful if you could ' - # 'react (by replying to this email) within the next two or three weeks, ' - # 'if possible. I\'ll be looking forward to your reaction, your comments ' - # 'and suggestions, be they positive or negative. If you need more time ' - # 'to consider, that\'s also fine; just let me know.\n\n' - # 'On behalf of the SciPost Foundation,\n\n' - # 'Prof. dr Jean-Sébastien Caux\n---------------------------------------------' - # '\nInstitute for Theoretial Physics\nUniversity of Amsterdam' - # '\nScience Park 904\n1098 XH Amsterdam\nThe Netherlands' - # '\n---------------------------------------------\n' - # 'tel.: +31 (0)20 5255775\nfax: +31 (0)20 5255778' - # '\n---------------------------------------------') - # email_text_html += ( - # '\n<p>You will perhaps have already heard about SciPost, a publication ' - # 'portal established by and for professional scientists. ' - # '\n<p>SciPost.org is legally based on a not-for-profit foundation and will ' - # 'operate in perpetuity as a non-commercial entity at the exclusive service ' - # 'of the academic sector, bringing a cost-slashing alternative to existing ' - # 'practices.</p>' - # '<p>SciPost offers a collection of two-way open ' - # 'access (no subscription fees, no author fees) journals with extremely ' - # 'stringent (peer-witnessed) refereeing, overseen by ' - # 'our Editorial College (exclusively composed ' - # 'of established, professionally practising scientists). The whole process is ' - # 'designed to ensure the highest achievable scientific quality while making the ' - # 'editorial workflow as light and efficient as possible.</p>' - # '\n<p>To go straight to the point, on behalf of the SciPost Foundation ' - # 'and in view of your professional expertise, I hereby would ' - # 'like to invite you to become an Editorial Fellow and thus join the ' - # 'Editorial College of SciPost Physics.</p>' - # '\n<p>Please note that only well-known and respected senior academics are ' - # 'being contacted for this purpose. Academic reputation and involvement ' - # 'in the community are the most important criteria guiding our ' - # 'considerations of who should belong to the Editorial College.</p>' - # '\n<p>To help you in considering this, it would be best if you were to take ' - # 'the time to look at the website itself, which is anchored at scipost.org. ' - # 'Besides looking around the site, you can also personally register ' - # '(to become a Contributor, without necessarily committing to membership ' - # 'of the Editorial College, this to be discussed separately) by visiting ' - # 'the following <a href="https://scipost.org/invitation/{{ invitation_key }}">' - # 'single-use link</a>, containing a partly pre-filled form for ' - # 'your convenience.</p>' - # '\n<p>Many details about the initiative ' - # 'can then be found at scipost.org/about and at scipost.org/FAQ. ' - # 'Functioning of the College will proceed according to the by-laws set ' - # 'out in scipost.org/EdCol_by-laws.</p>' - # '\n<p>Since the success of this initiative is dependent on the involvement of ' - # 'the very people it is meant to serve, we\'d be very grateful if you were ' - # 'to give due consideration to this proposal. We would expect you to ' - # 'commit just 2-4 hours per month to help perform Editorial duties; we will ' - # 'constantly adjust the number of Editorial Fellows to ensure this is the case. You ' - # 'could try it out for 6 months or a year, and of course you could quit ' - # 'any time you wished.</p>' - # '\n<p>I\'d be happy to provide you with more information, should you require ' - # 'it. In view of our development plans, I would be grateful if you could ' - # 'react (by replying to this email) within the next two or three weeks, ' - # 'if possible. I\'ll be looking forward to your reaction, your comments ' - # 'and suggestions, be they positive or negative. If you need more time ' - # 'to consider, that\'s also fine; just let me know.</p>' - # '<p>On behalf of the SciPost Foundation,</p>' - # '<br/>Prof. dr Jean-Sébastien Caux' - # '<br/>---------------------------------------------' - # '<br/>Institute for Theoretial Physics' - # '<br/>University of Amsterdam' - # '<br/>Science Park 904<br/>1098 XH Amsterdam<br/>The Netherlands' - # '<br/>---------------------------------------------' - # '<br/>tel.: +31 (0)20 5255775\nfax: +31 (0)20 5255778' - # '<br/>---------------------------------------------\n') - # - # email_text_html += '<br/>' + EMAIL_FOOTER - # html_template = Template(email_text_html) - # html_version = html_template.render(Context(email_context)) - # emailmessage = EmailMultiAlternatives( - # 'SciPost registration invitation', email_text, - # 'J-S Caux <jscaux@scipost.org>', - # [cls.invitation.email], - # cc=[cls.invitation.invited_by.user.email], - # bcc=['registration@scipost.org'], - # reply_to=['registration@scipost.org']) - # emailmessage.attach_alternative(html_version, 'text/html') - # - # # This function is now for all invitation types: - # emailmessage.send(fail_silently=False) - - @classmethod - def send_citation_notification_email(cls): - """ - Requires loading the 'notification' attribute. - """ - email_context = {} - email_text = ('Dear ' + cls.notification.contributor.get_title_display() + - ' ' + cls.notification.contributor.user.last_name) - email_text_html = 'Dear {{ title }} {{ last_name }}' - email_context['title'] = cls.notification.contributor.get_title_display() - email_context['last_name'] = cls.notification.contributor.user.last_name - email_text += ',\n\n' - email_text_html += ',<br/>' - if cls.notification.cited_in_publication: - url_unsubscribe = reverse('scipost:unsubscribe', - args=[cls.notification.contributor.id, - cls.notification.contributor.activation_key]) - email_text += ( - 'We would like to notify you that ' - 'your work has been cited in a paper published by SciPost,' - '\n\n' + cls.notification.cited_in_publication.title - + '\nby ' + cls.notification.cited_in_publication.author_list + - '\n\n(published as ' + cls.notification.cited_in_publication.citation() + - ').\n\nWe hope you will find this paper of interest to your own research.' - '\n\nBest regards,\n\nThe SciPost Team' - '\n\nDon\'t want to receive such emails? Unsubscribe by visiting ' - + url_unsubscribe + '.') - email_text_html += ( - '<p>We would like to notify you that ' - 'your work has been cited in a paper published by SciPost,</p>' - '<p>{{ title }}</p><p>by {{ pub_author_list }}</p>' - '<p>(published as <a href="https://scipost.org/{{ doi_label }}">' - '{{ citation }}</a>).</p>' - '<p>We hope you will find this paper of interest to your own research.</p>' - '<p>Best regards,</p><p>The SciPost Team</p><br/>' - + EMAIL_FOOTER + '<br/>' - '\n<p style="font-size: 10px;">Don\'t want to receive such emails? ' - '<a href="%s">Unsubscribe</a>.</p>' % url_unsubscribe) - email_context['title'] = cls.notification.cited_in_publication.title - email_context['pub_author_list'] = cls.notification.cited_in_publication.author_list - email_context['doi_label'] = cls.notification.cited_in_publication.doi_label - email_context['citation'] = cls.notification.cited_in_publication.citation() - email_context['key'] = cls.notification.contributor.activation_key - html_template = Template(email_text_html) - html_version = html_template.render(Context(email_context)) - elif cls.notification.cited_in_submission: - url_unsubscribe = reverse('scipost:unsubscribe', - args=[cls.notification.contributor.id, - cls.notification.contributor.activation_key]) - email_text += ( - 'Your work has been cited in a manuscript submitted to SciPost,' - '\n\n' + cls.notification.cited_in_submission.title - + ' by ' + cls.notification.cited_in_submission.author_list + '.\n\n' - 'You might for example consider reporting or ' - 'commenting on the above submission before the refereeing deadline.\n\n' - 'Best regards,\n\nThe SciPost Team' - '\n\nDon\'t want to receive such emails? Unsubscribe by visiting ' - + url_unsubscribe + '.') - email_text_html += ( - '<p>Your work has been cited in a manuscript submitted to SciPost,</p>' - '<p>{{ sub_title }} <br>by {{ sub_author_list }},</p>' - '<p>which you can find online at the ' - '<a href="https://scipost.org/submission/{{ arxiv_nr_w_vn_nr }}">' - 'submission\'s page</a>.</p>' - '<p>You might for example consider reporting or ' - 'commenting on the above submission before the refereeing deadline.</p>' - '<p>Best regards,</p><p>The SciPost Team</p><br/>' - + EMAIL_FOOTER + '<br/>' - '\n<p style="font-size: 10px;">Don\'t want to receive such emails? ' - '<a href="%s">Unsubscribe</a>.</p>' % url_unsubscribe) - email_context['sub_title'] = cls.notification.cited_in_submission.title - email_context['sub_author_list'] = cls.notification.cited_in_submission.author_list - email_context['arxiv_identifier_w_vn_nr'] = cls.notification.cited_in_submission.arxiv_identifier_w_vn_nr - email_context['key'] = cls.notification.contributor.activation_key - - emailmessage = EmailMultiAlternatives( - 'SciPost: citation notification', email_text, - 'SciPost admin <admin@scipost.org>', - [cls.notification.contributor.user.email], - bcc=['admin@scipost.org'], - reply_to=['admin@scipost.org']) - emailmessage.attach_alternative(html_version, 'text/html') - emailmessage.send(fail_silently=False) diff --git a/scipost/views.py b/scipost/views.py index bdcdfffc4..3097897d4 100644 --- a/scipost/views.py +++ b/scipost/views.py @@ -350,260 +350,6 @@ def registration_requests_reset(request, contributor_id): return redirect(reverse('scipost:registration_requests')) -# @permission_required('scipost.can_draft_registration_invitations', return_403=True) -# def draft_registration_invitation(request): -# """ -# For officers to prefill registration invitations. -# This is similar to the registration_invitations method, -# which is used to complete the invitation process. -# """ -# form = DraftInvitationForm(request.POST or None, current_user=request.user) -# if form.is_valid(): -# invitation = form.save(commit=False) -# invitation.drafted_by = request.user.contributor -# invitation.save() -# -# # Assign permission to 'drafter' to edit the draft afterwards -# assign_perm('comments.change_draftinvitation', request.user, invitation) -# messages.success(request, 'Draft invitation saved.') -# return redirect(reverse('scipost:draft_registration_invitation')) -# -# existing_drafts = DraftInvitation.objects.filter(processed=False).order_by('last_name') -# -# context = { -# 'form': form, -# 'existing_drafts': existing_drafts, -# } -# return render(request, 'scipost/draft_registration_invitation.html', context) - - -# @permission_required('scipost.can_draft_registration_invitations', return_403=True) -# def contributors_filter(request): -# """ -# For Invitation Officers that use lists of scientists as a to-do. This -# view returns all entries of those lists with users that are certainly not registered -# or invitated. -# """ -# names_found = names_not_found = invitations_found = None -# form = ContributorsFilterForm(request.POST or None) -# if form.is_valid(): -# names_found, names_not_found, invitations_found = form.filter() -# -# context = { -# 'form': form, -# 'names_found': names_found, -# 'names_not_found': names_not_found, -# 'invitations_found': invitations_found, -# } -# return render(request, 'scipost/contributors_filter.html', context) - - -# @login_required -# def draft_registration_invitation_form(request, draft_id): -# """ -# Edit DraftInvitation instance. It's only possible to edit istances created by the User itself. -# """ -# draft = get_object_or_404((get_objects_for_user(request.user, 'scipost.change_draftinvitation') -# .filter(processed=False)), -# id=draft_id) -# -# draft_inv_form = DraftInvitationForm(request.POST or None, current_user=request.user, -# instance=draft) -# if draft_inv_form.is_valid(): -# draft = draft_inv_form.save() -# messages.success(request, 'Draft invitation saved.') -# return redirect(reverse('scipost:registration_invitations')) -# -# context = {'draft_inv_form': draft_inv_form} -# return render(request, 'scipost/draft_registration_invitation_form.html', context) - - -# @permission_required('scipost.can_manage_registration_invitations', return_403=True) -# def map_draft_reg_inv_to_contributor(request, draft_id, contributor_id): -# """ -# If a draft invitation actually points to an already-registered -# Contributor, this method marks the draft invitation as processed -# and, if the draft invitation was for a citation type, -# creates an instance of CitationNotification. -# """ -# draft = get_object_or_404(DraftInvitation, id=draft_id) -# contributor = get_object_or_404(Contributor, id=contributor_id) -# draft.processed = True -# draft.save() -# citation = CitationNotification( -# contributor=contributor, -# cited_in_submission=draft.cited_in_submission, -# cited_in_publication=draft.cited_in_publication, -# processed=False) -# citation.save() -# return redirect(reverse('scipost:registration_invitations')) - - -# @permission_required('scipost.can_invite_fellows', return_403=True) -# def registration_invitations_form(request, draft_id): -# draft = get_object_or_404(DraftInvitation, id=draft_id) -# initial = { -# 'title': draft.title, -# 'first_name': draft.first_name, -# 'last_name': draft.last_name, -# 'email': draft.email, -# 'invitation_type': draft.invitation_type, -# 'cited_in_submission': draft.cited_in_submission, -# 'cited_in_publication': draft.cited_in_publication, -# } -# form = RegistrationInvitationForm(request.POST or None, initial=initial, -# current_user=request.user) -# mail_request = MailEditingSubView(request, mail_code='registration_invitation', -# invitation=draft) -# if form.is_valid(): -# if mail_request.is_valid(): -# invitation = form.save(commit=False) -# invitation.invited_by = request.user.contributor -# invitation.save() -# invitation.refresh_keys() -# -# Utils.load({'invitation': invitation}) -# Utils.send_registration_invitation_email() -# DraftInvitation.objects.filter(email=form.cleaned_data['email']).update(processed=True) -# -# messages.success(request, 'Registration Invitation sent') -# return redirect(reverse('scipost:registration_invitations')) -# else: -# mail_request.add_form(form) -# return mail_request.return_render() -# context = { -# 'form': form, -# } -# return render(request, 'scipost/registration_invitation_form.html', context) - - -# @permission_required('scipost.can_invite_fellows', return_403=True) -# def registration_invitation_list(request): -# """ Overview and tools for administrators """ -# sent_reg_inv = RegistrationInvitation.objects.filter(responded=False, declined=False) -# sent_reg_inv_fellows = sent_reg_inv.filter(invitation_type='F').order_by('last_name') -# sent_reg_inv_contrib = sent_reg_inv.filter(invitation_type='C').order_by('last_name') -# sent_reg_inv_ref = sent_reg_inv.filter(invitation_type='R').order_by('last_name') -# sent_reg_inv_cited_sub = sent_reg_inv.filter(invitation_type='ci').order_by('last_name') -# sent_reg_inv_cited_pub = sent_reg_inv.filter(invitation_type='cp').order_by('last_name') -# -# resp_reg_inv = RegistrationInvitation.objects.filter(responded=True, declined=False) -# resp_reg_inv_fellows = resp_reg_inv.filter(invitation_type='F').order_by('last_name') -# resp_reg_inv_contrib = resp_reg_inv.filter(invitation_type='C').order_by('last_name') -# resp_reg_inv_ref = resp_reg_inv.filter(invitation_type='R').order_by('last_name') -# resp_reg_inv_cited_sub = resp_reg_inv.filter(invitation_type='ci').order_by('last_name') -# resp_reg_inv_cited_pub = resp_reg_inv.filter(invitation_type='cp').order_by('last_name') -# -# decl_reg_inv = RegistrationInvitation.objects.filter(responded=True, declined=True) -# -# names_reg_contributors = Contributor.objects.active().order_by('user__last_name').values_list( -# 'user__first_name', 'user__last_name') -# existing_drafts = DraftInvitation.objects.filter( -# processed=False).order_by('last_name', 'email') -# -# context = { -# 'sent_reg_inv_fellows': sent_reg_inv_fellows, -# 'sent_reg_inv_contrib': sent_reg_inv_contrib, -# 'sent_reg_inv_ref': sent_reg_inv_ref, -# 'sent_reg_inv_cited_sub': sent_reg_inv_cited_sub, -# 'sent_reg_inv_cited_pub': sent_reg_inv_cited_pub, -# 'resp_reg_inv_fellows': resp_reg_inv_fellows, -# 'resp_reg_inv_contrib': resp_reg_inv_contrib, -# 'resp_reg_inv_ref': resp_reg_inv_ref, -# 'resp_reg_inv_cited_sub': resp_reg_inv_cited_sub, -# 'resp_reg_inv_cited_pub': resp_reg_inv_cited_pub, -# 'decl_reg_inv': decl_reg_inv, -# 'names_reg_contributors': names_reg_contributors, -# 'existing_drafts': existing_drafts, -# } -# return render(request, 'scipost/registration_invitation_list.html', context) - - -# @permission_required('scipost.can_manage_registration_invitations', return_403=True) -# def registration_invitations_cleanup(request): -# """ -# Compares the email addresses of invitations with those in the -# database of registered Contributors. Flags overlaps. -# """ -# contributor_email_list = Contributor.objects.values_list('user__email', flat=True) -# invs_to_cleanup = RegistrationInvitation.objects.filter( -# responded=False, email__in=contributor_email_list) -# context = {'invs_to_cleanup': invs_to_cleanup} -# return render(request, 'scipost/registration_invitations_cleanup.html', context) - - -# @permission_required('scipost.can_manage_registration_invitations', return_403=True) -# def remove_registration_invitation(request, invitation_id): -# """ -# Remove an invitation (called from registration_invitations_cleanup). -# """ -# invitation = get_object_or_404(RegistrationInvitation, pk=invitation_id) -# invitation.delete() -# return redirect(reverse('scipost:registration_invitations_cleanup')) - - -# @permission_required('scipost.can_invite_fellows', return_403=True) -# def renew_registration_invitation(request, invitation_id): -# """ -# Renew an invitation (called from registration_invitations). -# """ -# invitation = get_object_or_404(RegistrationInvitation, pk=invitation_id) -# -# # Utils.load({'invitation': invitation}) -# # Utils.send_registration_invitation_email(True) -# mail_request = MailEditingSubView(request, mail_code='registration_invitation_renewal', -# invitation=invitation) -# if mail_request.is_valid(): -# invitation.nr_reminders += 1 -# invitation.date_last_reminded = timezone.now() -# invitation.save() -# invitation.refresh_keys() -# messages.success(request, 'Registration invitation has been sent.') -# mail_request.send() -# return redirect('scipost:registration_invitations') -# else: -# return mail_request.return_render() - - -# @permission_required('scipost.can_manage_registration_invitations', return_403=True) -# def registration_invitation_mark_declined(request, invitation_id): -# """ -# Mark an invitation as declined (called from registration_invitation_list). -# """ -# invitation = get_object_or_404(RegistrationInvitation, pk=invitation_id) -# invitation.responded = True -# invitation.declined = True -# invitation.save() -# return redirect(reverse('scipost:registration_invitations')) - - -# @permission_required('scipost.can_manage_registration_invitations', return_403=True) -# def citation_notifications(request): -# unprocessed_notifications = CitationNotification.objects.filter( -# processed=False).order_by('contributor__user__last_name') -# context = {'unprocessed_notifications': unprocessed_notifications, } -# return render(request, 'scipost/citation_notifications.html', context) - - -# @permission_required('scipost.can_manage_registration_invitations', return_403=True) -# def process_citation_notification(request, cn_id): -# notification = get_object_or_404(CitationNotification, id=cn_id) -# notification.processed = True -# notification.save() -# if notification.contributor.accepts_SciPost_emails: -# Utils.load({'notification': notification}) -# Utils.send_citation_notification_email() -# return redirect(reverse('scipost:citation_notifications')) - - -# @permission_required('scipost.can_manage_registration_invitations', return_403=True) -# def draft_registration_invitation_processed(request, draft_id): -# draft = get_object_or_404(DraftInvitation, id=draft_id) -# draft.processed = True -# draft.save() -# return redirect(reverse('scipost:registration_invitations')) - - def login_view(request): """ This view shows and processes a user's login session. diff --git a/submissions/templatetags/lookup.py b/submissions/templatetags/lookup.py index c2f7e5491..5f1f0e24f 100644 --- a/submissions/templatetags/lookup.py +++ b/submissions/templatetags/lookup.py @@ -27,4 +27,4 @@ class SubmissionLookup(LookupChannel): Right now only used for draft registration invitations. May be extended in the future for other purposes as well. """ - return request.user.has_perm('can_draft_registration_invitations') + return request.user.has_perm('can_create_registration_invitations') diff --git a/submissions/views.py b/submissions/views.py index 838d26c1f..3e38c390d 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -40,11 +40,11 @@ from mails.views import MailEditingSubView from scipost.forms import ModifyPersonalMessageForm, RemarkForm from scipost.mixins import PaginationMixin from scipost.models import Contributor, Remark -from scipost.utils import Utils from comments.forms import CommentForm from invitations.constants import INVITATION_REFEREEING from invitations.models import RegistrationInvitation +from mails.utils import DirectMailUtil from production.forms import ProofsDecisionForm from production.models import ProductionStream @@ -770,14 +770,15 @@ def recruit_referee(request, arxiv_identifier_w_vn_nr): ref_invitation = ref_recruit_form.save(commit=False) ref_invitation.submission = submission ref_invitation.invited_by = request.user.contributor - ref_invitation.save() # Create and send a registration invitation - ref_inv_message_head = """ - On behalf of the Editor-in-charge {eic_title} {eic_last_name}, we would - like to invite you to referee a Submission to {journal}, - namely {sub_title} by {sub_author_list} (see https://scipost.org/{sub_url}). - """.format( + ref_inv_message_head = ( + 'On behalf of the Editor-in-charge {eic_title} {eic_last_name}, we would' + 'like to invite you to referee a Submission to {journal}, namely' + '\n{sub_title}' + '\nby {sub_author_list}' + '\n(see https://scipost.org/{sub_url}).' + ).format( eic_title=submission.editor_in_charge.get_title_display(), eic_last_name=submission.editor_in_charge.user.last_name, journal=submission.get_submitted_to_journal_display(), @@ -790,18 +791,20 @@ def recruit_referee(request, arxiv_identifier_w_vn_nr): last_name=ref_recruit_form.cleaned_data['last_name'], email=ref_recruit_form.cleaned_data['email_address'], invitation_type=INVITATION_REFEREEING, - invited_by=request.user.contributor, + created_by=request.user.contributor.user, + invited_by=request.user.contributor.user, personal_message=ref_inv_message_head) reg_invitation.save() - Utils.load({'invitation': reg_invitation}) - Utils.send_registration_invitation_email() + # Copy the key to the refereeing invitation + ref_invitation.invitation_key = reg_invitation.invitation_key + ref_invitation.save() + mail_sender = DirectMailUtil(mail_code='registration_invitation', + instance=reg_invitation) + mail_sender.send() submission.add_event_for_author('A referee has been invited.') submission.add_event_for_eic('%s has been recruited and invited as a referee.' % ref_recruit_form.cleaned_data['last_name']) - # Copy the key to the refereeing invitation: - ref_invitation.invitation_key = reg_invitation.invitation_key - ref_invitation.save() return redirect(reverse('submissions:editorial_page', kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) -- GitLab