diff --git a/mails/templates/mail_templates/registration_invitation_renewal.html b/mails/templates/mail_templates/registration_invitation_renewal.html new file mode 100644 index 0000000000000000000000000000000000000000..223cf91dbdc978289f979d3a5ee7f1488fa4866e --- /dev/null +++ b/mails/templates/mail_templates/registration_invitation_renewal.html @@ -0,0 +1,272 @@ +{% if invitation.nr_reminders > 0 %} + <p><strong>Reminder: Invitation to SciPost</strong></p> +{% endif %} + +{% if invitation.invitation_type == 'F' %} + <p><strong>RE: Invitation to join the Editorial College of SciPost</strong></p> +{% endif %} + + +<p> + Dear + {% if invitation.message_style == 'F' %} + {{ invitation.get_title_display }} {{ invitation.last_name }} + {% else %} + {{ invitation.first_name }} + {% endif %}, +</p> + +{% if invitation.invitation_type == 'R' %} + <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.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.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> +{% elif invitation.invitation_type == 'ci' %} + <p> + Your work has been cited in a manuscript submitted to SciPost, {{ invitation.cited_in_submission.title }} <br>by {{ invitation.cited_in_submission.author_list }}, <br> + which you can find online at the + <a href="https://scipost.org/submission/{{ invitation.cited_in_submission.arxiv_identifier_w_vn_nr }}"> + submission\'s page</a>. + </p> + <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> + + + <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> + <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> + <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> + <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> + <p>Many thanks in advance for taking a few minutes to look into it,</p> + <p>On behalf of the SciPost Foundation,</p> + <p>{{ invitation.invited_by.get_title_display }} {{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</p> + +{% elif invitation.invitation_type == 'cp' %} + <p>Your work has been cited in a paper published by SciPost,</p> + <p> + {{ invitation.cited_in_publication.title }}</p> <p>by {{ invitation.cited_in_publication.author_list }} (published as <a href="https://scipost.org/{{ invitation.cited_in_publication.doi_label }}">{{ invitation.cited_in_publication.citation }}</a>. + </p> + <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> + + + <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> + <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> + <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> + <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> + <p>Many thanks in advance for taking a few minutes to look into it,</p> + <p>On behalf of the SciPost Foundation,</p> + <p>{{ invitation.invited_by.get_title_display }} {{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</p> + +{% elif invitation.invitation_type == 'C' %} + <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> + + + <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> + <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> + <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> + <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> + <p>Many thanks in advance for taking a few minutes to look into it,</p> + <p>On behalf of the SciPost Foundation,</p> + <p>{{ invitation.invited_by.get_title_display }} {{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</p> + +{% elif invitation.invitation_type == 'F' %} + <p> + You will perhaps have already heard about SciPost, a publication + portal established by and for professional scientists. + </p> + <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> + <p> + To go straight to the point, on behalf of the SciPost Foundation + and in view of your professional expertise, I hereby would + ike to invite you to become an Editorial Fellow and thus join the + Editorial College of SciPost Physics. + </p> + <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> + <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.invitation_key }}"> + single-use link</a>, containing a partly pre-filled form for + your convenience.</p> + <p> + Many details about the initiative + can then be found at <a href="https://scipost.org/about">SciPost About</a> and at <a href="https://scipost.org/FAQ">SciPost FAQ</a>. + Functioning of the College will proceed according to the by-laws set + out in <a href="https://scipost.org/EdCol_by-laws">the by-laws</a>. + </p> + <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> + <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, + <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/>--------------------------------------------- + </p> +{% endif %} diff --git a/mails/templates/mail_templates/registration_invitation_renewal.json b/mails/templates/mail_templates/registration_invitation_renewal.json new file mode 100644 index 0000000000000000000000000000000000000000..9941b614623cf8f70ca83bcfbf4f934307d93b3f --- /dev/null +++ b/mails/templates/mail_templates/registration_invitation_renewal.json @@ -0,0 +1,8 @@ +{ + "subject": "SciPost: invitation", + "to_address": "email", + "bcc_to": "invited_by.user.email", + "from_address_name": "J-S Caux", + "from_address": "jscaux@scipost.org", + "context_object": "invitation" +} diff --git a/mails/widgets.py b/mails/widgets.py index d5f1aff3003b38e75cacf58fc5b279304e883491..1754950616856af0813450a14037a0cdc95760b2 100644 --- a/mails/widgets.py +++ b/mails/widgets.py @@ -3,9 +3,6 @@ import json from django.core.urlresolvers import reverse, NoReverseMatch from django.forms import widgets, Media from django.utils.safestring import mark_safe -# from django.conf import settings - -# from . import PLUGINS, PLUGINS_WITH_CSS class SummernoteEditor(widgets.Textarea): @@ -23,6 +20,7 @@ class SummernoteEditor(widgets.Textarea): ['font', ['strikethrough', 'superscript', 'subscript']], ['fontsize', ['fontsize']], ['para', ['ul', 'ol', 'paragraph']], + ['insert', ['link', 'hr']] ], } @@ -34,10 +32,7 @@ class SummernoteEditor(widgets.Textarea): except NoReverseMatch: default_options['fileUpload'] = False - # settings_options = getattr(settings, 'FROALA_EDITOR_OPTIONS', {}) - # options = dict(default_options.items() + settings_options.items() + self.options.items()) options = dict(default_options.items()).copy() - # options.update(settings_options.items()) options.update(self.options.items()) json_options = json.dumps(options) diff --git a/scipost/management/commands/add_groups_and_permissions.py b/scipost/management/commands/add_groups_and_permissions.py index 1b99ccf50734665e25491a3b6b0e8934057d33d0..35c279649c84fc40da52a185334e9ecacea13701 100644 --- a/scipost/management/commands/add_groups_and_permissions.py +++ b/scipost/management/commands/add_groups_and_permissions.py @@ -314,6 +314,7 @@ class Command(BaseCommand): EditorialAdmin.permissions.set([ can_view_pool, + can_invite_Fellows, can_assign_submissions, can_do_plagiarism_checks, can_oversee_refereeing, diff --git a/scipost/models.py b/scipost/models.py index cd56f991ddf98372a1e4323676f50f879de20ed9..c289ded4c241c022a29d3a73408cf48fef8e0055 100644 --- a/scipost/models.py +++ b/scipost/models.py @@ -219,6 +219,18 @@ class RegistrationInvitation(models.Model): 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): contributor = models.ForeignKey('scipost.Contributor', on_delete=models.CASCADE) diff --git a/scipost/templates/scipost/_draft_registration_tables.html b/scipost/templates/scipost/_draft_registration_tables.html index d0909ac9068a93196bdaadb663b869ec96fdb0b9..c0284e05f513e43b82db434f455aa0e9943a2655 100644 --- a/scipost/templates/scipost/_draft_registration_tables.html +++ b/scipost/templates/scipost/_draft_registration_tables.html @@ -1,351 +1,394 @@ <div class="row"> <div class="col-12"> <h2 class="highlight">Invitations sent (response pending)</h2> + <a href="javascript:void(0)" data-toggle="toggle" data-target="#invitations_sent">view/hide</a> - <h3>Editorial Fellows ({{sent_reg_inv_fellows|length}}) - <a href="javascript:void(0)" data-toggle="toggle" data-target="#table_sent_reg_inv_fellows">view/hide</a></h3> + <div id="invitations_sent"> + <h3>Editorial Fellows ({{sent_reg_inv_fellows|length}})</h3> - <table class="table" id="table_sent_reg_inv_fellows" style="display: none;"> - <thead> - <tr> - <th>Last name</th> - <th>First name</th> - <th>Email</th> - <th>Date sent</th> - <th>Type</th> - <th>Invited by</th> - </tr> - </thead> - <tbody> - {% for fellow in sent_reg_inv_fellows %} - <tr> - <td>{{ fellow.last_name }}</td> - <td>{{ fellow.first_name }}</td> - <td>{{ fellow.email }}</td> - <td>{{ fellow.date_sent }} </td> - <td>{{ fellow.get_invitation_type_display }}</td> - <td>{{ fellow.invited_by.user.first_name }} {{ fellow.invited_by.user.last_name }}</td> - </tr> - {% empty %} + <table class="table" id="table_sent_reg_inv_fellows"> + <thead> <tr> - <td colspan="6">No invitations found.</td> + <th>Last name</th> + <th>First name</th> + <th>Email</th> + <th>Date sent</th> + <th>Type</th> + <th>Invited by</th> + <th></th> </tr> - {% endfor %} - </tbody> - </table> + </thead> + <tbody> + {% for fellow in sent_reg_inv_fellows %} + <tr> + <td>{{ fellow.last_name }}</td> + <td>{{ fellow.first_name }}</td> + <td>{{ fellow.email }}</td> + <td>{{ fellow.date_sent }} </td> + <td>{{ fellow.get_invitation_type_display }}</td> + <td>{{ fellow.invited_by.user.first_name }} {{ fellow.invited_by.user.last_name }}</td> + <td> + {% if perms.scipost.can_invite_Fellows %} + <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 %} + · + <a href="{% url 'scipost:mark_reg_inv_as_declined' invitation_id=fellow.id %}">Declined</a> + {% endif %} + </td> - <h3>Normal Contributors ({{sent_reg_inv_contrib|length}}) - <a href="javascript:void(0)" data-toggle="toggle" data-target="#table_sent_reg_inv_contrib">view/hide</a></h3> - <table class="table" id="table_sent_reg_inv_contrib" style="display: none;"> - <thead> - <tr> - <th>Last name</th> - <th>First name</th> - <th>Email</th> - <th>Date sent</th> - <th>Type</th> - <th>Invited by</th> - </tr> - </thead> - <tbody> - {% for invitation in sent_reg_inv_contrib %} - <tr> - <td>{{ invitation.last_name }}</td> - <td>{{ invitation.first_name }}</td> - <td>{{ invitation.email }}</td> - <td>{{ invitation.date_sent }} </td> - <td>{{ invitation.get_invitation_type_display }}</td> - <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> - </tr> - {% empty %} + </tr> + {% empty %} + <tr> + <td colspan="7">No invitations found.</td> + </tr> + {% endfor %} + </tbody> + </table> + + <h3>Normal Contributors ({{sent_reg_inv_contrib|length}})</h3> + <table class="table" id="table_sent_reg_inv_contrib"> + <thead> <tr> - <td colspan="6">No invitations found.</td> + <th>Last name</th> + <th>First name</th> + <th>Email</th> + <th>Date sent</th> + <th>Type</th> + <th>Invited by</th> + <th></th> </tr> - {% endfor %} - </tbody> - </table> + </thead> + <tbody> + {% for invitation in sent_reg_inv_contrib %} + <tr> + <td>{{ invitation.last_name }}</td> + <td>{{ invitation.first_name }}</td> + <td>{{ invitation.email }}</td> + <td>{{ invitation.date_sent }} </td> + <td>{{ invitation.get_invitation_type_display }}</td> + <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> + <td> + {% if perms.scipost.can_invite_Fellows %} + <a href="{% url 'scipost:renew_registration_invitation' invitation_id=invitation.id %}">Renew</a> ({{ invitation.nr_reminders }}) {% if invitation.date_last_reminded %}(last: {{ invitation.date_last_reminded|date:"Y-m-d" }}){% endif %} + · + <a href="{% url 'scipost:mark_reg_inv_as_declined' invitation_id=invitation.id %}">Declined</a> + {% endif %} + </td> + </tr> + {% empty %} + <tr> + <td colspan="7">No invitations found.</td> + </tr> + {% endfor %} + </tbody> + </table> - <h3>Referees ({{sent_reg_inv_ref|length}}) - <a href="javascript:void(0)" data-toggle="toggle" data-target="#table_sent_reg_inv_ref">view/hide</a></h3> - <table class="table" id="table_sent_reg_inv_ref" style="display: none;"> - <thead> - <tr> - <th>Last name</th> - <th>First name</th> - <th>Email</th> - <th>Date sent</th> - <th>Type</th> - <th>Invited by</th> - </tr> - </thead> - <tbody> - {% for invitation in sent_reg_inv_ref %} - <tr> - <td>{{ invitation.last_name }}</td> - <td>{{ invitation.first_name }}</td> - <td>{{ invitation.email }}</td> - <td>{{ invitation.date_sent }} </td> - <td>{{ invitation.get_invitation_type_display }}</td> - <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> - </tr> - {% empty %} + <h3>Referees ({{sent_reg_inv_ref|length}})</h3> + <table class="table" id="table_sent_reg_inv_ref"> + <thead> <tr> - <td colspan="6">No invitations found.</td> + <th>Last name</th> + <th>First name</th> + <th>Email</th> + <th>Date sent</th> + <th>Type</th> + <th>Invited by</th> + <th></th> </tr> - {% endfor %} - </tbody> - </table> + </thead> + <tbody> + {% for invitation in sent_reg_inv_ref %} + <tr> + <td>{{ invitation.last_name }}</td> + <td>{{ invitation.first_name }}</td> + <td>{{ invitation.email }}</td> + <td>{{ invitation.date_sent }} </td> + <td>{{ invitation.get_invitation_type_display }}</td> + <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> + <td> + {% if perms.scipost.can_invite_Fellows %} + <a href="{% url 'scipost:renew_registration_invitation' invitation_id=invitation.id %}">Renew</a> ({{ invitation.nr_reminders }}) {% if invitation.date_last_reminded %}(last: {{ invitation.date_last_reminded|date:"Y-m-d" }}){% endif %} + {% endif %} + </td> + </tr> + {% empty %} + <tr> + <td colspan="7">No invitations found.</td> + </tr> + {% endfor %} + </tbody> + </table> - <h3>Cited in sub ({{sent_reg_inv_cited_sub|length}}) - <a href="javascript:void(0)" data-toggle="toggle" data-target="#table_sent_reg_inv_cited_sub">view/hide</a></h3> - <table class="table" id="table_sent_reg_inv_cited_sub" style="display: none;"> - <thead> - <tr> - <th>Last name</th> - <th>First name</th> - <th>Email</th> - <th>Date sent</th> - <th>Type</th> - <th>Invited by</th> - </tr> - </thead> - <tbody> - {% for invitation in sent_reg_inv_cited_sub %} - <tr> - <td>{{ invitation.last_name }}</td> - <td>{{ invitation.first_name }}</td> - <td>{{ invitation.email }}</td> - <td>{{ invitation.date_sent }} </td> - <td>{{ invitation.get_invitation_type_display }}</td> - <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> - </tr> - {% empty %} + <h3>Cited in sub ({{sent_reg_inv_cited_sub|length}})</h3> + <table class="table" id="table_sent_reg_inv_cited_sub"> + <thead> <tr> - <td colspan="6">No invitations found.</td> + <th>Last name</th> + <th>First name</th> + <th>Email</th> + <th>Date sent</th> + <th>Type</th> + <th>Invited by</th> + <th></th> </tr> - {% endfor %} - </tbody> - </table> + </thead> + <tbody> + {% for invitation in sent_reg_inv_cited_sub %} + <tr> + <td>{{ invitation.last_name }}</td> + <td>{{ invitation.first_name }}</td> + <td>{{ invitation.email }}</td> + <td>{{ invitation.date_sent }} </td> + <td>{{ invitation.get_invitation_type_display }}</td> + <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> + <td> + {% if perms.scipost.can_invite_Fellows %} + <a href="{% url 'scipost:renew_registration_invitation' invitation_id=invitation.id %}">Renew</a> ({{ invitation.nr_reminders }}) {% if invitation.date_last_reminded %}(last: {{ invitation.date_last_reminded|date:"Y-m-d" }}){% endif %} + {% endif %} + </td> + </tr> + {% empty %} + <tr> + <td colspan="7">No invitations found.</td> + </tr> + {% endfor %} + </tbody> + </table> - <h3>Cited in pub ({{sent_reg_inv_cited_pub|length}}) - <a href="javascript:void(0)" data-toggle="toggle" data-target="#table_sent_reg_inv_cited_pub">view/hide</a></h3> - <table class="table" id="table_sent_reg_inv_cited_pub" style="display: none;"> - <thead> - <tr> - <th>Last name</th> - <th>First name</th> - <th>Email</th> - <th>Date sent</th> - <th>Type</th> - <th>Invited by</th> - </tr> - </thead> - <tbody> - {% for invitation in sent_reg_inv_cited_pub %} - <tr> - <td>{{ invitation.last_name }}</td> - <td>{{ invitation.first_name }}</td> - <td>{{ invitation.email }}</td> - <td>{{ invitation.date_sent }} </td> - <td>{{ invitation.get_invitation_type_display }}</td> - <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> - </tr> - {% empty %} + <h3>Cited in pub ({{sent_reg_inv_cited_pub|length}})</h3> + <table class="table" id="table_sent_reg_inv_cited_pub"> + <thead> <tr> - <td colspan="6">No invitations found.</td> + <th>Last name</th> + <th>First name</th> + <th>Email</th> + <th>Date sent</th> + <th>Type</th> + <th>Invited by</th> + <th></th> </tr> - {% endfor %} - </tbody> - </table> + </thead> + <tbody> + {% for invitation in sent_reg_inv_cited_pub %} + <tr> + <td>{{ invitation.last_name }}</td> + <td>{{ invitation.first_name }}</td> + <td>{{ invitation.email }}</td> + <td>{{ invitation.date_sent }} </td> + <td>{{ invitation.get_invitation_type_display }}</td> + <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> + <td> + {% if perms.scipost.can_invite_Fellows %} + <a href="{% url 'scipost:renew_registration_invitation' invitation_id=invitation.id %}">Renew</a> ({{ invitation.nr_reminders }}) {% if invitation.date_last_reminded %}(last: {{ invitation.date_last_reminded|date:"Y-m-d" }}){% endif %} + {% endif %} + </td> + </tr> + {% empty %} + <tr> + <td colspan="7">No invitations found.</td> + </tr> + {% endfor %} + </tbody> + </table> + </div> </div> </div> <div class="row"> <div class="col-12"> <h2 class="highlight">Invitations sent (responded)</h2> + <a href="javascript:void(0)" data-toggle="toggle" data-target="#invitations_responded">view/hide</a> - <h3>Editorial Fellows ({{resp_reg_inv_fellow|length}}) - <a href="javascript:void(0)" data-toggle="toggle" data-target="#table_resp_reg_inv_fellow">view/hide</a></h3> - <table class="table" id="table_resp_reg_inv_fellow" style="display: none;"> - <thead> - <tr> - <th>Last name</th> - <th>First name</th> - <th>Email</th> - <th>Date sent</th> - <th>Type</th> - <th>Invited by</th> - </tr> - </thead> - <tbody> - {% for invitation in resp_reg_inv_fellow %} - <tr> - <td>{{ invitation.last_name }}</td> - <td>{{ invitation.first_name }}</td> - <td>{{ invitation.email }}</td> - <td>{{ invitation.date_sent }} </td> - <td>{{ invitation.get_invitation_type_display }}</td> - <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> - </tr> - {% empty %} + <div id="invitations_responded"> + <h3>Editorial Fellows ({{resp_reg_inv_fellow|length}})</h3> + <table class="table" id="table_resp_reg_inv_fellow"> + <thead> <tr> - <td colspan="6">No invitations found.</td> + <th>Last name</th> + <th>First name</th> + <th>Email</th> + <th>Date sent</th> + <th>Type</th> + <th>Invited by</th> </tr> - {% endfor %} - </tbody> - </table> + </thead> + <tbody> + {% for invitation in resp_reg_inv_fellow %} + <tr> + <td>{{ invitation.last_name }}</td> + <td>{{ invitation.first_name }}</td> + <td>{{ invitation.email }}</td> + <td>{{ invitation.date_sent }} </td> + <td>{{ invitation.get_invitation_type_display }}</td> + <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> + </tr> + {% empty %} + <tr> + <td colspan="6">No invitations found.</td> + </tr> + {% endfor %} + </tbody> + </table> - <h3>Normal Contributors ({{resp_reg_inv_contrib|length}}) - <a href="javascript:void(0)" data-toggle="toggle" data-target="#table_resp_reg_inv_contrib">view/hide</a></h3> - <table class="table" id="table_resp_reg_inv_contrib" style="display: none;"> - <thead> - <tr> - <th>Last name</th> - <th>First name</th> - <th>Email</th> - <th>Date sent</th> - <th>Type</th> - <th>Invited by</th> - </tr> - </thead> - <tbody> - {% for invitation in resp_reg_inv_contrib %} - <tr> - <td>{{ invitation.last_name }}</td> - <td>{{ invitation.first_name }}</td> - <td>{{ invitation.email }}</td> - <td>{{ invitation.date_sent }} </td> - <td>{{ invitation.get_invitation_type_display }}</td> - <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> - </tr> - {% empty %} + <h3>Normal Contributors ({{resp_reg_inv_contrib|length}})</h3> + <table class="table" id="table_resp_reg_inv_contrib"> + <thead> <tr> - <td colspan="6">No invitations found.</td> + <th>Last name</th> + <th>First name</th> + <th>Email</th> + <th>Date sent</th> + <th>Type</th> + <th>Invited by</th> </tr> - {% endfor %} - </tbody> - </table> + </thead> + <tbody> + {% for invitation in resp_reg_inv_contrib %} + <tr> + <td>{{ invitation.last_name }}</td> + <td>{{ invitation.first_name }}</td> + <td>{{ invitation.email }}</td> + <td>{{ invitation.date_sent }} </td> + <td>{{ invitation.get_invitation_type_display }}</td> + <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> + </tr> + {% empty %} + <tr> + <td colspan="6">No invitations found.</td> + </tr> + {% endfor %} + </tbody> + </table> - <h3>Referees ({{resp_reg_inv_ref|length}}) - <a href="javascript:void(0)" data-toggle="toggle" data-target="#table_resp_reg_inv_ref">view/hide</a></h3> - <table class="table" id="table_resp_reg_inv_ref" style="display: none;"> - <thead> - <tr> - <th>Last name</th> - <th>First name</th> - <th>Email</th> - <th>Date sent</th> - <th>Type</th> - <th>Invited by</th> - </tr> - </thead> - <tbody> - {% for invitation in resp_reg_inv_ref %} - <tr> - <td>{{ invitation.last_name }}</td> - <td>{{ invitation.first_name }}</td> - <td>{{ invitation.email }}</td> - <td>{{ invitation.date_sent }} </td> - <td>{{ invitation.get_invitation_type_display }}</td> - <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> - </tr> - {% empty %} + <h3>Referees ({{resp_reg_inv_ref|length}})</h3> + <table class="table" id="table_resp_reg_inv_ref"> + <thead> <tr> - <td colspan="6">No invitations found.</td> + <th>Last name</th> + <th>First name</th> + <th>Email</th> + <th>Date sent</th> + <th>Type</th> + <th>Invited by</th> </tr> - {% endfor %} - </tbody> - </table> + </thead> + <tbody> + {% for invitation in resp_reg_inv_ref %} + <tr> + <td>{{ invitation.last_name }}</td> + <td>{{ invitation.first_name }}</td> + <td>{{ invitation.email }}</td> + <td>{{ invitation.date_sent }} </td> + <td>{{ invitation.get_invitation_type_display }}</td> + <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> + </tr> + {% empty %} + <tr> + <td colspan="6">No invitations found.</td> + </tr> + {% endfor %} + </tbody> + </table> - <h3>Cited in sub ({{resp_reg_inv_cited_sub|length}}) - <a href="javascript:void(0)" data-toggle="toggle" data-target="#table_resp_reg_inv_cited_sub">view/hide</a></h3> - <table class="table" id="table_resp_reg_inv_cited_sub" style="display: none;"> - <thead> - <tr> - <th>Last name</th> - <th>First name</th> - <th>Email</th> - <th>Date sent</th> - <th>Type</th> - <th>Invited by</th> - </tr> - </thead> - <tbody> - {% for invitation in resp_reg_inv_cited_sub %} - <tr> - <td>{{ invitation.last_name }}</td> - <td>{{ invitation.first_name }}</td> - <td>{{ invitation.email }}</td> - <td>{{ invitation.date_sent }} </td> - <td>{{ invitation.get_invitation_type_display }}</td> - <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> - </tr> - {% empty %} + <h3>Cited in sub ({{resp_reg_inv_cited_sub|length}})</h3> + <table class="table" id="table_resp_reg_inv_cited_sub"> + <thead> <tr> - <td colspan="6">No invitations found.</td> + <th>Last name</th> + <th>First name</th> + <th>Email</th> + <th>Date sent</th> + <th>Type</th> + <th>Invited by</th> </tr> - {% endfor %} - </tbody> - </table> + </thead> + <tbody> + {% for invitation in resp_reg_inv_cited_sub %} + <tr> + <td>{{ invitation.last_name }}</td> + <td>{{ invitation.first_name }}</td> + <td>{{ invitation.email }}</td> + <td>{{ invitation.date_sent }} </td> + <td>{{ invitation.get_invitation_type_display }}</td> + <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> + </tr> + {% empty %} + <tr> + <td colspan="6">No invitations found.</td> + </tr> + {% endfor %} + </tbody> + </table> - <h3>Cited in pub ({{resp_reg_inv_cited_pub|length}}) - <a href="javascript:void(0)" data-toggle="toggle" data-target="#table_resp_reg_inv_cited_pub">view/hide</a></h3> - <table class="table" id="table_resp_reg_inv_cited_pub" style="display: none;"> - <thead> - <tr> - <th>Last name</th> - <th>First name</th> - <th>Email</th> - <th>Date sent</th> - <th>Type</th> - <th>Invited by</th> - </tr> - </thead> - <tbody> - {% for invitation in resp_reg_inv_cited_pub %} - <tr> - <td>{{ invitation.last_name }}</td> - <td>{{ invitation.first_name }}</td> - <td>{{ invitation.email }}</td> - <td>{{ invitation.date_sent }} </td> - <td>{{ invitation.get_invitation_type_display }}</td> - <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> - </tr> - {% empty %} + <h3>Cited in pub ({{resp_reg_inv_cited_pub|length}})</h3> + <table class="table" id="table_resp_reg_inv_cited_pub"> + <thead> <tr> - <td colspan="6">No invitations found.</td> + <th>Last name</th> + <th>First name</th> + <th>Email</th> + <th>Date sent</th> + <th>Type</th> + <th>Invited by</th> </tr> - {% endfor %} - </tbody> - </table> + </thead> + <tbody> + {% for invitation in resp_reg_inv_cited_pub %} + <tr> + <td>{{ invitation.last_name }}</td> + <td>{{ invitation.first_name }}</td> + <td>{{ invitation.email }}</td> + <td>{{ invitation.date_sent }} </td> + <td>{{ invitation.get_invitation_type_display }}</td> + <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> + </tr> + {% empty %} + <tr> + <td colspan="6">No invitations found.</td> + </tr> + {% endfor %} + </tbody> + </table> - <h3>Declined ({{decl_reg_inv|length}}) - <a href="javascript:void(0)" data-toggle="toggle" data-target="#table_decl_reg_inv">view/hide</a></h3> - <table class="table" id="table_decl_reg_inv" style="display: none;"> - <thead> - <tr> - <th>Last name</th> - <th>First name</th> - <th>Email</th> - <th>Date sent</th> - <th>Type</th> - <th>Invited by</th> - </tr> - </thead> - <tbody> - {% for invitation in decl_reg_inv %} - <tr> - <td>{{ invitation.last_name }}</td> - <td>{{ invitation.first_name }}</td> - <td>{{ invitation.email }}</td> - <td>{{ invitation.date_sent }} </td> - <td>{{ invitation.get_invitation_type_display }}</td> - <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> - </tr> - {% empty %} + <h3>Declined ({{decl_reg_inv|length}})</h3> + <table class="table" id="table_decl_reg_inv"> + <thead> <tr> - <td colspan="6">No invitations found.</td> + <th>Last name</th> + <th>First name</th> + <th>Email</th> + <th>Date sent</th> + <th>Type</th> + <th>Invited by</th> </tr> - {% endfor %} - </tbody> - </table> + </thead> + <tbody> + {% for invitation in decl_reg_inv %} + <tr> + <td>{{ invitation.last_name }}</td> + <td>{{ invitation.first_name }}</td> + <td>{{ invitation.email }}</td> + <td>{{ invitation.date_sent }} </td> + <td>{{ invitation.get_invitation_type_display }}</td> + <td>{{ invitation.invited_by.user.first_name }} {{ invitation.invited_by.user.last_name }}</td> + </tr> + {% empty %} + <tr> + <td colspan="6">No invitations found.</td> + </tr> + {% endfor %} + </tbody> + </table> + </div> </div> </div> <div class="row"> <div class="col-12"> - <h2 class="highlight">List of already-registered contributors ({{names_reg_contributors|length}}) <small><a href="javascript:void(0)" data-toggle="toggle" data-target="#registered_contributors">view/hide</a></small></h3> + <h2 class="highlight">List of already-registered contributors ({{names_reg_contributors|length}})</h3> + <a href="javascript:void(0)" data-toggle="toggle" data-target="#registered_contributors">view/hide</a> + <div class="card-columns" id="registered_contributors" style="display: none;"> {% for first_name, last_name in names_reg_contributors %} <div class="card border-0"> diff --git a/scipost/templates/scipost/registration_invitations.html b/scipost/templates/scipost/registration_invitations.html index a495c7ce7be80a89ee415f1daa8428276ec7e04e..c32f893c5ffcf5add6c927a91e2aae5d6ddaa685 100644 --- a/scipost/templates/scipost/registration_invitations.html +++ b/scipost/templates/scipost/registration_invitations.html @@ -64,7 +64,9 @@ $(document).ready(function(){ <div class="row"> <div class="col-12"> - <h2 class="highlight">Existing drafts (to be processed by Admin) ({{existing_drafts|length}}) <small><a href="javascript:void(0)" data-toggle="toggle" data-target="#table_existing_drafts">view/hide</a></small></h2> + <h2 class="highlight">Existing drafts (to be processed by Admin) ({{existing_drafts|length}})</h2> + <a href="javascript:void(0)" data-toggle="toggle" data-target="#table_existing_drafts">view/hide</a> + <table class="table" id="table_existing_drafts"> <thead> <tr> diff --git a/scipost/views.py b/scipost/views.py index 3269094efa55060fc8723935289b4c863e2f14eb..858b004e79829bd2f4ae61483d1714def50eebdb 100644 --- a/scipost/views.py +++ b/scipost/views.py @@ -39,6 +39,7 @@ from affiliations.forms import AffiliationsFormset from commentaries.models import Commentary from comments.models import Comment from journals.models import Publication, Journal +from mails.views import MailEditingSubView from news.models import NewsItem from submissions.models import Submission, RefereeInvitation,\ Report, EICRecommendation @@ -440,7 +441,7 @@ def map_draft_reg_inv_to_contributor(request, draft_id, contributor_id): return redirect(reverse('scipost:registration_invitations')) -@permission_required('scipost.can_manage_registration_invitations', return_403=True) +@permission_required('scipost.can_invite_Fellows', return_403=True) def registration_invitations(request, draft_id=None): """ Overview and tools for administrators """ # List invitations sent; send new ones @@ -468,6 +469,7 @@ def registration_invitations(request, draft_id=None): invitation = reg_inv_form.save(commit=False) invitation.invited_by = request.user.contributor invitation.save() + invitation.refresh_keys() Utils.load({'invitation': invitation}) Utils.send_registration_invitation_email() @@ -568,26 +570,27 @@ def edit_invitation_personal_message(request, invitation_id): return render(request, 'scipost/edit_invitation_personal_message.html', context) -@permission_required('scipost.can_manage_registration_invitations', return_403=True) +@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) - errormessage = None - if(invitation.invitation_type == 'F' - and not request.user.has_perm('scipost.can_invite_Fellows')): - errormessage = ('You do not have the authorization to send a Fellow-type ' - 'invitation. Consider Contributor, or cited (sub/pub). ') - elif invitation.invitation_type == 'R': - errormessage = ('Referee-type invitations must be made by the Editor-in-charge ' - 'at the relevant Submission\'s Editorial Page. ') - if errormessage is not None: - return render(request, 'scipost/error.html', context={'errormessage': errormessage}) - - Utils.load({'invitation': invitation}) - Utils.send_registration_invitation_email(True) - return redirect(reverse('scipost:registration_invitations')) + + # 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 have 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)