From ea9e79d0a814d3210222f0f62e4225435da233a2 Mon Sep 17 00:00:00 2001 From: "J.-S. Caux" <J.S.Caux@uva.nl> Date: Tue, 20 Sep 2016 08:30:36 +0200 Subject: [PATCH] html version of contrib invitation email --- scipost/forms.py | 8 +- scipost/models.py | 6 +- .../scipost/registration_invitations.html | 54 ++++- scipost/urls.py | 71 +++++-- scipost/utils.py | 193 ++++++++++++++---- scipost/views.py | 37 +++- 6 files changed, 290 insertions(+), 79 deletions(-) diff --git a/scipost/forms.py b/scipost/forms.py index 0eb7cdc73..6e86d1d46 100644 --- a/scipost/forms.py +++ b/scipost/forms.py @@ -12,6 +12,7 @@ from crispy_forms.layout import Layout, Div, Field, Fieldset, HTML, Submit from .models import * +from journals.models import Publication from submissions.models import SUBMISSION_STATUS_PUBLICLY_UNLISTED from submissions.models import Submission @@ -56,7 +57,9 @@ class RegistrationInvitationForm(forms.ModelForm): class Meta: model = RegistrationInvitation fields = ['title', 'first_name', 'last_name', 'email', - 'invitation_type', 'cited_in_submission', 'message_style', 'personal_message'] + 'invitation_type', + 'cited_in_submission', 'cited_in_publication', + 'message_style', 'personal_message'] def __init__(self, *args, **kwargs): super(RegistrationInvitationForm, self).__init__(*args, **kwargs) @@ -65,6 +68,8 @@ class RegistrationInvitationForm(forms.ModelForm): self.fields['cited_in_submission'] = forms.ModelChoiceField( queryset=Submission.objects.all().exclude( status__in=SUBMISSION_STATUS_PUBLICLY_UNLISTED).order_by('-submission_date')) + self.fields['cited_in_publication'] = forms.ModelChoiceField( + queryset=Publication.objects.all().order_by('-publication_date')) self.helper = FormHelper() self.helper.layout = Layout( Div( @@ -79,6 +84,7 @@ class RegistrationInvitationForm(forms.ModelForm): css_class="col-6"), css_class="row"), Div(Field('cited_in_submission'),), + Div(Field('cited_in_publication'),), ) class UpdateUserDataForm(forms.ModelForm): diff --git a/scipost/models.py b/scipost/models.py index ea94d2156..28caa4746 100644 --- a/scipost/models.py +++ b/scipost/models.py @@ -318,7 +318,8 @@ INVITATION_TYPE = ( ('F', 'Editorial Fellow'), ('C', 'Contributor'), ('R', 'Refereeing'), - ('ci', 'cited'), + ('ci', 'cited in submission'), + ('cp', 'cited in publication'), ) INVITATION_STYLE = ( @@ -336,12 +337,15 @@ class RegistrationInvitation(models.Model): email = models.EmailField() invitation_type = models.CharField(max_length=2, choices=INVITATION_TYPE, default='C') cited_in_submission = models.ForeignKey('submissions.Submission', blank=True, null=True) + cited_in_publication = models.ForeignKey('journals.Publication', blank=True, null=True) message_style = models.CharField(max_length=1, choices=INVITATION_STYLE, default='F') personal_message = models.TextField(blank=True, null=True) invitation_key = models.CharField(max_length=40, default='') key_expires = models.DateTimeField(default=timezone.now) date_sent = models.DateTimeField(default=timezone.now) invited_by = models.ForeignKey(Contributor, blank=True, null=True) + nr_reminders = models.PositiveSmallIntegerField(default=0) + date_last_reminded = models.DateTimeField(blank=True, null=True) responded = models.BooleanField(default=False) def __str__ (self): diff --git a/scipost/templates/scipost/registration_invitations.html b/scipost/templates/scipost/registration_invitations.html index 5197150b3..c1c3509dc 100644 --- a/scipost/templates/scipost/registration_invitations.html +++ b/scipost/templates/scipost/registration_invitations.html @@ -9,14 +9,21 @@ $(document).ready(function(){ $("#div_id_cited_in_submission").hide(); + $("#div_id_cited_in_publication").hide(); $('select#id_invitation_type').on('change', function() { switch ($('select#id_invitation_type').val()) { case "ci": $("#div_id_cited_in_submission").show(); + $("#div_id_cited_in_publication").hide(); + break; + case "cp": + $("#div_id_cited_in_submission").hide(); + $("#div_id_cited_in_publication").show(); break; default: $("#div_id_cited_in_submission").hide(); + $("#div_id_cited_in_publication").hide(); } }); }); @@ -44,7 +51,7 @@ <hr class="hr12"/> <section> <div class="flex-greybox"> - <h2>Invitations sent (response pending) EF ({{ nr_sent_reg_inv_fellows }}), C ({{ nr_sent_reg_inv_contrib }}), R ({{ nr_sent_reg_inv_ref }}), cited ({{ nr_sent_reg_inv_cited }}):</h2> + <h2>Invitations sent (response pending) EF ({{ nr_sent_reg_inv_fellows }}), C ({{ nr_sent_reg_inv_contrib }}), R ({{ nr_sent_reg_inv_ref }}), cited in sub ({{ nr_sent_reg_inv_cited_sub }}), cited in pub ({{ nr_sent_reg_inv_cited_pub }}):</h2> </div> <hr class="hr6"/> <h3>Editorial Fellows ({{ nr_sent_reg_inv_fellows }})</h3> @@ -58,6 +65,7 @@ <td>{{ fellow.date_sent }} </td> <td>{{ fellow.invitation_type }}</td> <td>{{ fellow.invited_by.user.last_name }}</td> + <td><a href="{% url 'scipost:renew_registration_invitation' invitation_id=fellow.id %}">Renew</a> ({{ fellow.nr_reminders }}) {% if fellow.date_last_reminded %}(last: {{ fellow.date_last_reminded|date:"Y-m-d" }}){% endif %}</td> </tr> {% endfor %} </table> @@ -73,6 +81,7 @@ <td>{{ fellow.date_sent }} </td> <td>{{ fellow.invitation_type }}</td> <td>{{ fellow.invited_by.user.last_name }}</td> + <td><a href="{% url 'scipost:renew_registration_invitation' invitation_id=fellow.id %}">Renew</a> ({{ fellow.nr_reminders }}) {% if fellow.date_last_reminded %}(last: {{ fellow.date_last_reminded|date:"Y-m-d" }}){% endif %}</td> </tr> {% endfor %} </table> @@ -92,10 +101,26 @@ {% endfor %} </table> <hr class="hr6"/> - <h3>Cited ({{ nr_sent_reg_inv_cited }})</h3> + <h3>Cited in sub ({{ nr_sent_reg_inv_cited_sub }})</h3> + <table class="tableofInvitees"> + <tr><td>Last name</td><td>First name</td><td>Email</td><td>Date sent</td><td>Type</td><td>Invited by</td></tr> + {% for fellow in sent_reg_inv_cited_sub %} + <tr> + <td>{{ fellow.last_name }}</td> + <td>{{ fellow.first_name }}</td> + <td>{{ fellow.email }}</td> + <td>{{ fellow.date_sent }} </td> + <td>{{ fellow.invitation_type }}</td> + <td>{{ fellow.invited_by.user.last_name }}</td> + <td><a href="{% url 'scipost:renew_registration_invitation' invitation_id=fellow.id %}">Renew</a> ({{ fellow.nr_reminders }}) {% if fellow.date_last_reminded %}(last: {{ fellow.date_last_reminded|date:"Y-m-d" }}){% endif %}</td> + </tr> + {% endfor %} + </table> + <hr class="hr6"/> + <h3>Cited in pub ({{ nr_sent_reg_inv_cited_pub }})</h3> <table class="tableofInvitees"> <tr><td>Last name</td><td>First name</td><td>Email</td><td>Date sent</td><td>Type</td><td>Invited by</td></tr> - {% for fellow in sent_reg_inv_cited %} + {% for fellow in sent_reg_inv_cited_pub %} <tr> <td>{{ fellow.last_name }}</td> <td>{{ fellow.first_name }}</td> @@ -103,6 +128,7 @@ <td>{{ fellow.date_sent }} </td> <td>{{ fellow.invitation_type }}</td> <td>{{ fellow.invited_by.user.last_name }}</td> + <td><a href="{% url 'scipost:renew_registration_invitation' invitation_id=fellow.id %}">Renew</a> ({{ fellow.nr_reminders }}) {% if fellow.date_last_reminded %}(last: {{ fellow.date_last_reminded|date:"Y-m-d" }}){% endif %}</td> </tr> {% endfor %} </table> @@ -110,7 +136,7 @@ <hr class="hr12"/> <section> <div class="flex-greybox"> - <h2>Invitations sent (responded) EF ({{ nr_resp_reg_inv_fellows }}), C ({{ nr_resp_reg_inv_contrib }}), R ({{ nr_resp_reg_inv_ref }}), cited({{ nr_resp_reg_inv_cited }}):</h2> + <h2>Invitations sent (responded) EF ({{ nr_resp_reg_inv_fellows }}), C ({{ nr_resp_reg_inv_contrib }}), R ({{ nr_resp_reg_inv_ref }}), cited in sub ({{ nr_resp_reg_inv_cited_sub }}), cited in pub ({{ nr_resp_reg_inv_cited_pub }}):</h2> </div> <hr class="hr6"/> <h3>Editorial Fellows ({{ nr_resp_reg_inv_fellows }})</h3> @@ -160,10 +186,26 @@ </table> <hr class="hr6"/> - <h3>Cited ({{ nr_resp_reg_inv_cited }})</h3> + <h3>Cited in sub ({{ nr_resp_reg_inv_cited_sub }})</h3> + <table class="tableofInviteesResponded"> + <tr><td>Last name</td><td>First name</td><td>Email</td><td>Date sent</td><td>Type</td><td>Invited by</td></tr> + {% for fellow in resp_reg_inv_cited_sub %} + <tr> + <td>{{ fellow.last_name }}</td> + <td>{{ fellow.first_name }}</td> + <td>{{ fellow.email }}</td> + <td>{{ fellow.date_sent }} </td> + <td>{{ fellow.invitation_type }}</td> + <td>{{ fellow.invited_by.user.last_name }}</td> + </tr> + {% endfor %} + </table> + + <hr class="hr6"/> + <h3>Cited in pub ({{ nr_resp_reg_inv_cited_pub }})</h3> <table class="tableofInviteesResponded"> <tr><td>Last name</td><td>First name</td><td>Email</td><td>Date sent</td><td>Type</td><td>Invited by</td></tr> - {% for fellow in resp_reg_inv_cited %} + {% for fellow in resp_reg_inv_cited_pub %} <tr> <td>{{ fellow.last_name }}</td> <td>{{ fellow.first_name }}</td> diff --git a/scipost/urls.py b/scipost/urls.py index cabfd887a..f0f88c1c3 100644 --- a/scipost/urls.py +++ b/scipost/urls.py @@ -20,11 +20,15 @@ urlpatterns = [ url(r'^news$', views.news, name='news'), url(r'^about$', TemplateView.as_view(template_name='scipost/about.html'), name='about'), url(r'^call$', TemplateView.as_view(template_name='scipost/call.html'), name='call'), - url(r'^foundation$', TemplateView.as_view(template_name='scipost/foundation.html'), name='foundation'), + url(r'^foundation$', TemplateView.as_view(template_name='scipost/foundation.html'), + name='foundation'), url(r'^tour$', TemplateView.as_view(template_name='scipost/quick_tour.html'), name='quick_tour'), url(r'^FAQ$', TemplateView.as_view(template_name='scipost/FAQ.html'), name='FAQ'), - url(r'^terms_and_conditions$', TemplateView.as_view(template_name='scipost/terms_and_conditions.html'), name='terms_and_conditions'), - url(r'^privacy_policy$', TemplateView.as_view(template_name='scipost/privacy_policy.html'), name='privacy_policy'), + url(r'^terms_and_conditions$', + TemplateView.as_view(template_name='scipost/terms_and_conditions.html'), + name='terms_and_conditions'), + url(r'^privacy_policy$', TemplateView.as_view(template_name='scipost/privacy_policy.html'), + name='privacy_policy'), # Feeds url(r'^feeds$', TemplateView.as_view(template_name='scipost/feeds.html'), name='feeds'), @@ -42,24 +46,40 @@ urlpatterns = [ ## Registration url(r'^register$', views.register, name='register'), - url(r'^thanks_for_registering$', TemplateView.as_view(template_name='scipost/thanks_for_registering.html'), name='thanks_for_registering'), + url(r'^thanks_for_registering$', + TemplateView.as_view(template_name='scipost/thanks_for_registering.html'), + name='thanks_for_registering'), url(r'^activation/(?P<key>.+)$', views.activation, name='activation'), - url(r'^request_new_activation_link/(?P<oldkey>.+)$', views.request_new_activation_link, name='request_new_activation_link'), - url(r'^already_activated$', TemplateView.as_view(template_name='scipost/already_activated.html'), name='already_activated'), - url(r'^vet_registration_requests$', views.vet_registration_requests, name='vet_registration_requests'), - url(r'^vet_registration_request_ack/(?P<contributor_id>[0-9]+)$', views.vet_registration_request_ack, name='vet_registration_request_ack'), - url(r'^registration_invitations$', views.registration_invitations, name="registration_invitations"), - url(r'^registration_invitation_sent$', TemplateView.as_view(template_name='scipost/registration_invitation_sent.html'), name='registration_invitation_sent'), + url(r'^request_new_activation_link/(?P<oldkey>.+)$', + views.request_new_activation_link, + name='request_new_activation_link'), + url(r'^already_activated$', + TemplateView.as_view(template_name='scipost/already_activated.html'), + name='already_activated'), + url(r'^vet_registration_requests$', + views.vet_registration_requests, name='vet_registration_requests'), + url(r'^vet_registration_request_ack/(?P<contributor_id>[0-9]+)$', + views.vet_registration_request_ack, name='vet_registration_request_ack'), + url(r'^registration_invitations$', + views.registration_invitations, name="registration_invitations"), + url(r'^renew_registration_invitation/(?P<invitation_id>[0-9]+)$', + views.renew_registration_invitation, name="renew_registration_invitation"), + url(r'^registration_invitation_sent$', + TemplateView.as_view(template_name='scipost/registration_invitation_sent.html'), + name='registration_invitation_sent'), #url(r'^invitation/(?P<key>.+)$', views.accept_invitation, name='accept_invitation'), url(r'^invitation/(?P<key>.+)$', views.invitation, name='invitation'), - url(r'^accept_invitation_error$', TemplateView.as_view(template_name='scipost/accept_invitation_error.html'), name='accept_invitation_error'), + url(r'^accept_invitation_error$', + TemplateView.as_view(template_name='scipost/accept_invitation_error.html'), + name='accept_invitation_error'), ## Authentication url(r'^login/$', views.login_view, name='login'), url(r'^logout$', views.logout_view, name='logout'), url(r'^personal_page$', views.personal_page, name='personal_page'), url(r'^change_password$', views.change_password, name='change_password'), - url(r'^reset_password_confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$', views.reset_password_confirm, name='reset_password_confirm'), + url(r'^reset_password_confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$', + views.reset_password_confirm, name='reset_password_confirm'), url(r'^reset_password/$', views.reset_password, name='reset_password'), url(r'^update_personal_data$', views.update_personal_data, name='update_personal_data'), @@ -71,11 +91,15 @@ urlpatterns = [ # Authorship claims url(r'^claim_authorships$', views.claim_authorships, name="claim_authorships"), - url(r'^claim_sub_authorship/(?P<submission_id>[0-9]+)/(?P<claim>[0-1])$', views.claim_sub_authorship, name='claim_sub_authorship'), - url(r'^claim_com_authorship/(?P<commentary_id>[0-9]+)/(?P<claim>[0-1])$', views.claim_com_authorship, name='claim_com_authorship'), - url(r'^claim_thesis_authorship/(?P<thesis_id>[0-9]+)/(?P<claim>[0-1])$', views.claim_thesis_authorship, name='claim_thesis_authorship'), + url(r'^claim_sub_authorship/(?P<submission_id>[0-9]+)/(?P<claim>[0-1])$', + views.claim_sub_authorship, name='claim_sub_authorship'), + url(r'^claim_com_authorship/(?P<commentary_id>[0-9]+)/(?P<claim>[0-1])$', + views.claim_com_authorship, name='claim_com_authorship'), + url(r'^claim_thesis_authorship/(?P<thesis_id>[0-9]+)/(?P<claim>[0-1])$', + views.claim_thesis_authorship, name='claim_thesis_authorship'), url(r'^vet_authorship_claims$', views.vet_authorship_claims, name="vet_authorship_claims"), - url(r'^vet_authorship_claim/(?P<claim_id>[0-9]+)/(?P<claim>[0-1])$', views.vet_authorship_claim, name='vet_authorship_claim'), + url(r'^vet_authorship_claim/(?P<claim_id>[0-9]+)/(?P<claim>[0-1])$', + views.vet_authorship_claim, name='vet_authorship_claim'), #################### @@ -113,18 +137,23 @@ urlpatterns = [ url(r'^create_list$', views.create_list, name='create_list'), url(r'^list/(?P<list_id>[0-9]+)$', views.list, name='list'), - url(r'^list_add_element/(?P<list_id>[0-9]+)/(?P<type>[SCTc])/(?P<element_id>[0-9]+)$', views.list_add_element, name='list_add_element'), - url(r'^list_remove_element/(?P<list_id>[0-9]+)/(?P<type>[SCTc])/(?P<element_id>[0-9]+)$', views.list_remove_element, name='list_remove_element'), + url(r'^list_add_element/(?P<list_id>[0-9]+)/(?P<type>[SCTc])/(?P<element_id>[0-9]+)$', + views.list_add_element, name='list_add_element'), + url(r'^list_remove_element/(?P<list_id>[0-9]+)/(?P<type>[SCTc])/(?P<element_id>[0-9]+)$', + views.list_remove_element, name='list_remove_element'), # Teams url(r'^create_team$', views.create_team, name='create_team'), url(r'^add_team_member/(?P<team_id>[0-9]+)$', views.add_team_member, name='add_team_member'), - url(r'^add_team_member/(?P<team_id>[0-9]+)/(?P<contributor_id>[0-9]+)$', views.add_team_member, name='add_team_member'), + url(r'^add_team_member/(?P<team_id>[0-9]+)/(?P<contributor_id>[0-9]+)$', + views.add_team_member, name='add_team_member'), # Graphs url(r'^create_graph$', views.create_graph, name='create_graph'), url(r'^graph/(?P<graph_id>[0-9]+)$', views.graph, name='graph'), - url(r'^edit_graph_node/(?P<node_id>[0-9]+)$', views.edit_graph_node, name='edit_graph_node'), - url(r'^delete_graph_node/(?P<node_id>[0-9]+)$', views.delete_graph_node, name='delete_graph_node'), + url(r'^edit_graph_node/(?P<node_id>[0-9]+)$', + views.edit_graph_node, name='edit_graph_node'), + url(r'^delete_graph_node/(?P<node_id>[0-9]+)$', + views.delete_graph_node, name='delete_graph_node'), url(r'^api/graph/(?P<graph_id>[0-9]+)$', views.api_graph, name='api_graph'), ] diff --git a/scipost/utils.py b/scipost/utils.py index d3524aada..02d8505d7 100644 --- a/scipost/utils.py +++ b/scipost/utils.py @@ -4,7 +4,8 @@ import random import string from django.contrib.auth.models import User -from django.core.mail import EmailMessage +from django.core.mail import EmailMessage, EmailMultiAlternatives +from django.template import Context, Template from django.utils import timezone from .models import * @@ -143,61 +144,120 @@ class Utils(object): Utils.load({'invitation': invitation}) @classmethod - def send_registration_invitation_email(cls): - # 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() + def send_registration_invitation_email(cls, renew=False): + 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 = 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 += 'RE: Invitation to join the Editorial College of SciPost<br/><hr/><br/>' email_text += 'Dear ' + email_text_html += 'Dear ' if cls.invitation.message_style == 'F': email_text += title_dict[cls.invitation.title] + ' ' + cls.invitation.last_name + email_text_html += '{{ title }} {{ last_name }}' + email_context['title'] = title_dict[cls.invitation.title] + 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/><br/>' if len(cls.invitation.personal_message) > 3: email_text += cls.invitation.personal_message + '\n\n' - + email_text_html += '{{ personal_message|linebreaks }}<br/><br/>' # 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, I have prepared a partly pre-filled registration ' - 'form at https://scipost.org/invitation/' + cls.invitation.invitation_key - + ' (valid for up to a year; you can thereafter still register at ' - 'https://scipost.org/register).\n\n' - 'If you do develop sympathy for the initiative, besides participating in the ' - 'online platform, I 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. I\'ll also be looking forward to your reaction, ' - 'comments and suggestions about the initiative, which I 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' - 'Prof. dr Jean-Sébastien Caux\n---------------------------------------------' - '\nInstitute for Theoretical Physics\nUniversity of Amsterdam\nScience Park 904' - '\n1098 XH Amsterdam\nThe Netherlands\n' - '---------------------------------------------\ntel.: +31 (0)20 5255775' - '\nfax: +31 (0)20 5255778\n---------------------------------------------') + 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, I have prepared a partly pre-filled registration ' + 'form at https://scipost.org/invitation/' + cls.invitation.invitation_key + + ' (valid for up to a year; you can thereafter still register at ' + 'https://scipost.org/register).\n\n' + 'If you do develop sympathy for the initiative, besides participating in the ' + 'online platform, I 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. I\'ll also be looking forward to your reaction, ' + 'comments and suggestions about the initiative, which I 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' + 'Prof. dr Jean-Sébastien Caux\n---------------------------------------------' + '\nInstitute for Theoretical Physics\nUniversity of Amsterdam\nScience Park 904' + '\n1098 XH Amsterdam\nThe Netherlands\n' + '---------------------------------------------\ntel.: +31 (0)20 5255775' + '\nfax: +31 (0)20 5255778\n---------------------------------------------') + summary_text_html = ( + '<br/><br/>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.' + '<br/><br/>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.' + '<br/><br/>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.' + '<br/><br/>For your convenience, I have prepared a partly pre-filled ' + '<a href="https://scipost.org/invitation/{{ invitation_key }}>registration form</a>' + ' (valid for up to a year; you can thereafter still register at the ' + '<a href="https://scipost.org/register">registration page</a>).<br/><br/>' + 'If you do develop sympathy for the initiative, besides participating in the ' + 'online platform, I 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. I\'ll also be looking forward to your reaction, ' + 'comments and suggestions about the initiative, which I hope you will find ' + 'useful to your work as a professional scientist.' + '<br/><br/>Many thanks in advance for taking a few minutes to look into it,' + '<br/><br/>On behalf of the SciPost Foundation,<br/><br/>' + 'Prof. dr Jean-Sébastien Caux<br/>' + '---------------------------------------------' + '<br/>Institute for Theoretical Physics' + '<br/>University of Amsterdam' + '<br/>Science Park 904' + '<br/>1098 XH Amsterdam<br/>The Netherlands<br/>' + '---------------------------------------------' + '<br/>tel.: +31 (0)20 5255775' + '<br/>fax: +31 (0)20 5255778' + '<br/>---------------------------------------------') + email_context['invitation_key'] = cls.invitation.invitation_key if cls.invitation.invitation_type == 'R': # Refereeing invitation @@ -212,6 +272,17 @@ class Utils(object): 'in particular by providing referee reports.\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 += ( + '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.<br/><br/>' + 'We very much hope that we can count on your expertise,<br/><br/>' + 'Many thanks in advance,\n\nThe SciPost Team') email_text += ('\n\n--------------------------------------------------' '\n\nAbout SciPost:\n\n' 'In summary, SciPost.org is a publication portal managed by ' @@ -223,6 +294,18 @@ class Utils(object): '\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.') + email_text_html += ( + '<br/><br/>--------------------------------------------------' + '<br/><br/>About SciPost:<br/><br/>' + '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.' + '<br/><br/>The 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.') emailmessage = EmailMessage( 'SciPost: refereeing request (and registration invitation)', email_text, @@ -248,17 +331,45 @@ class Utils(object): ['registration@scipost.org'], reply_to=['registration@scipost.org']) + 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 + + ' by ' + 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. You might for example consider reporting or ' + 'commenting on the above submission before the refereeing deadline.') + email_text += summary_text + emailmessage = EmailMessage( + 'SciPost: invitation', email_text, + 'J.-S. Caux <jscaux@scipost.org>', + [cls.invitation.email], + ['registration@scipost.org'], + reply_to=['registration@scipost.org']) + elif cls.invitation.invitation_type == 'C': email_text += ('I would hereby like to quickly introduce ' 'you to a scientific publishing initiative I recently launched, ' 'called SciPost, and to invite you to become an active Contributor.') email_text += summary_text - emailmessage = EmailMessage( + email_text_html += ( + 'I would hereby like to quickly introduce ' + 'you to a scientific publishing initiative I recently launched, ' + 'called SciPost, and to invite you to become an active Contributor.') + email_text_html += summary_text_html + '<br/><br/>' + EMAIL_FOOTER + html_template = Template(email_text_html) + html_version = html_template.render(email_context) + #emailmessage = EmailMessage( + emailmessage = EmailMultiAlternatives( 'SciPost: invitation', email_text, 'J.-S. Caux <jscaux@scipost.org>', [cls.invitation.email], ['registration@scipost.org'], reply_to=['registration@scipost.org']) + emailmessage.attach_alternative(html_version, 'text/html') elif cls.invitation.invitation_type == 'F': email_text += ('You will have noticed that scientific publishing is currently ' diff --git a/scipost/views.py b/scipost/views.py index 2ab275ce6..e56bf12b0 100644 --- a/scipost/views.py +++ b/scipost/views.py @@ -18,7 +18,7 @@ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.urlresolvers import reverse from django.http import HttpResponse, HttpResponseRedirect, JsonResponse from django.shortcuts import redirect -from django.template import RequestContext +from django.template import Context, RequestContext, Template from django.utils.http import is_safe_url from django.views.decorators.csrf import csrf_protect from django.db.models import Avg @@ -37,6 +37,7 @@ from .utils import * from commentaries.models import Commentary from commentaries.forms import CommentarySearchForm from comments.models import Comment +from journals.models import Publication from submissions.models import SUBMISSION_STATUS_PUBLICLY_UNLISTED from submissions.models import Submission, EditorialAssignment, RefereeInvitation, Report, EICRecommendation from submissions.forms import SubmissionSearchForm @@ -474,8 +475,10 @@ def registration_invitations(request): nr_sent_reg_inv_contrib = sent_reg_inv_contrib.count() sent_reg_inv_ref = sent_reg_inv.filter(invitation_type='R').order_by('last_name') nr_sent_reg_inv_ref = sent_reg_inv_ref.count() - sent_reg_inv_cited = sent_reg_inv.filter(invitation_type='ci').order_by('last_name') - nr_sent_reg_inv_cited = sent_reg_inv_cited.count() + sent_reg_inv_cited_sub = sent_reg_inv.filter(invitation_type='ci').order_by('last_name') + nr_sent_reg_inv_cited_sub = sent_reg_inv_cited_sub.count() + sent_reg_inv_cited_pub = sent_reg_inv.filter(invitation_type='cp').order_by('last_name') + nr_sent_reg_inv_cited_pub = sent_reg_inv_cited_pub.count() resp_reg_inv = RegistrationInvitation.objects.filter(responded=True) resp_reg_inv_fellows = resp_reg_inv.filter(invitation_type='F').order_by('last_name') @@ -484,8 +487,10 @@ def registration_invitations(request): nr_resp_reg_inv_contrib = resp_reg_inv_contrib.count() resp_reg_inv_ref = resp_reg_inv.filter(invitation_type='R').order_by('last_name') nr_resp_reg_inv_ref = resp_reg_inv_ref.count() - resp_reg_inv_cited = resp_reg_inv.filter(invitation_type='ci').order_by('last_name') - nr_resp_reg_inv_cited = resp_reg_inv_cited.count() + resp_reg_inv_cited_sub = resp_reg_inv.filter(invitation_type='ci').order_by('last_name') + nr_resp_reg_inv_cited_sub = resp_reg_inv_cited_sub.count() + resp_reg_inv_cited_pub = resp_reg_inv.filter(invitation_type='cp').order_by('last_name') + nr_resp_reg_inv_cited_pub = resp_reg_inv_cited_pub.count() context = {'reg_inv_form': reg_inv_form, 'errormessage': errormessage, 'sent_reg_inv_fellows': sent_reg_inv_fellows, @@ -494,19 +499,33 @@ def registration_invitations(request): 'nr_sent_reg_inv_contrib': nr_sent_reg_inv_contrib, 'sent_reg_inv_ref': sent_reg_inv_ref, 'nr_sent_reg_inv_ref': nr_sent_reg_inv_ref, - 'sent_reg_inv_cited': sent_reg_inv_cited, - 'nr_sent_reg_inv_cited': nr_sent_reg_inv_cited, + 'sent_reg_inv_cited_sub': sent_reg_inv_cited_sub, + 'nr_sent_reg_inv_cited_sub': nr_sent_reg_inv_cited_sub, + 'sent_reg_inv_cite_pub': sent_reg_inv_cited_pub, + 'nr_sent_reg_inv_cited_pub': nr_sent_reg_inv_cited_pub, 'resp_reg_inv_fellows': resp_reg_inv_fellows, 'nr_resp_reg_inv_fellows': nr_resp_reg_inv_fellows, 'resp_reg_inv_contrib': resp_reg_inv_contrib, 'nr_resp_reg_inv_contrib': nr_resp_reg_inv_contrib, 'resp_reg_inv_ref': resp_reg_inv_ref, 'nr_resp_reg_inv_ref': nr_resp_reg_inv_ref, - 'resp_reg_inv_cited': resp_reg_inv_cited, - 'nr_resp_reg_inv_cited': nr_resp_reg_inv_cited, } + 'resp_reg_inv_cited_sub': resp_reg_inv_cited_sub, + 'nr_resp_reg_inv_cited_sub': nr_resp_reg_inv_cited_sub, + 'resp_reg_inv_cited_pub': resp_reg_inv_cited_pub, + 'nr_resp_reg_inv_cited_pub': nr_resp_reg_inv_cited_pub, } return render(request, 'scipost/registration_invitations.html', context) +@permission_required('scipost.can_manage_registration_invitations', 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) + return redirect(reverse('scipost:registration_invitations')) + def login_view(request): redirect_to = request.POST.get('next', -- GitLab