diff --git a/comments/views.py b/comments/views.py index 021b7f7303530480c8b8eab4bc0dd405e3753491..e4c909d39fca62cefd2dd7360672ce3291a789f8 100644 --- a/comments/views.py +++ b/comments/views.py @@ -129,12 +129,18 @@ def reply_to_comment(request, comment_id): comment = get_object_or_404(Comment, pk=comment_id) # Verify if this is from an author: - try: - # Submission/Commentary - is_author = comment.content_object.authors.filter(id=request.user.contributor.id).exists() - except AttributeError: + related_object = comment.content_object + if isinstance(related_object, Submission) or isinstance(related_object, Commentary): + is_author = related_object.authors.filter(id=request.user.contributor.id).exists() + elif isinstance(related_object, Report): + is_author = related_object.submission.authors.filter( + id=request.user.contributor.id).exists() + elif isinstance(related_object, ThesisLink): # ThesisLink - is_author = comment.content_object.author == request.user.contributor + is_author = related_object.author == request.user.contributor + else: + # No idea what this could be, but just to be sure + is_author = related_object.author == request.user.contributor form = CommentForm(request.POST or None, request.FILES or None) if form.is_valid(): diff --git a/journals/views.py b/journals/views.py index 4d9c2e619d662ed9c0eefcfdfc454d69a3caef4a..160cee4591d95f60e4eb99ae58df0604dab09bfa 100644 --- a/journals/views.py +++ b/journals/views.py @@ -248,6 +248,10 @@ def validate_publication(request): #publication.pdf_file = request.FILES['pdf_file'] submission = publication.accepted_submission publication.authors.add(*submission.authors.all()) + if publication.first_author: + publication.authors.add(publication.first_author) + if publication.first_author_unregistered: + publication.authors_unregistered.add(publication.first_author_unregistered) publication.authors_claims.add(*submission.authors_claims.all()) publication.authors_false_claims.add(*submission.authors_false_claims.all()) publication.save() diff --git a/mails/forms.py b/mails/forms.py index c277051d2d46c036c918608a1148e787da8a2115..fd1feb9cb95dcef96c1f321560be835f56c61633 100644 --- a/mails/forms.py +++ b/mails/forms.py @@ -1,3 +1,4 @@ +import re import json import inspect from html2text import HTML2Text @@ -62,14 +63,19 @@ class EmailTemplateForm(forms.Form): # Get recipients list. Try to send through BCC to prevent privacy issues! bcc_list = [] if self.mail_data.get('bcc_to') and self.object: - 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] + if re.match("[^@]+@[^@]+\.[^@]+", self.mail_data.get('bcc_to')): + bcc_list = [self.mail_data.get('bcc_to')] else: - bcc_list = bcc_to + 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')) diff --git a/mails/templates/mail_templates/partners_followup_mail.json b/mails/templates/mail_templates/partners_followup_mail.json index efb95bbc8882bb10b321d44ed84cb72bcede49a0..e2a4c15705f549d843406715290456ef0ab61545 100644 --- a/mails/templates/mail_templates/partners_followup_mail.json +++ b/mails/templates/mail_templates/partners_followup_mail.json @@ -1,6 +1,7 @@ { "subject": "SciPost: Supporting Partners Board", "to_address": "email", + "bcc_to": "partners@scipost.org", "from_address_name": "SciPost Supporting Partners", "from_address": "partners@scipost.org", "context_object": "contact" diff --git a/mails/templates/mail_templates/partners_initial_mail.json b/mails/templates/mail_templates/partners_initial_mail.json index efb95bbc8882bb10b321d44ed84cb72bcede49a0..e2a4c15705f549d843406715290456ef0ab61545 100644 --- a/mails/templates/mail_templates/partners_initial_mail.json +++ b/mails/templates/mail_templates/partners_initial_mail.json @@ -1,6 +1,7 @@ { "subject": "SciPost: Supporting Partners Board", "to_address": "email", + "bcc_to": "partners@scipost.org", "from_address_name": "SciPost Supporting Partners", "from_address": "partners@scipost.org", "context_object": "contact" diff --git a/partners/constants.py b/partners/constants.py index a00f453a7dafe9df8dd6283377d5fffd55909b98..6aeb94d3c9aabf5a3af07b190c2838f74c9e7e09 100644 --- a/partners/constants.py +++ b/partners/constants.py @@ -20,6 +20,7 @@ PARTNER_KINDS = ( PROSPECTIVE_PARTNER_REQUESTED = 'requested' PROSPECTIVE_PARTNER_ADDED = 'added' PROSPECTIVE_PARTNER_APPROACHED = 'approached' +PROSPECTIVE_PARTNER_FOLLOWED_UP = 'followuped' PROSPECTIVE_PARTNER_NEGOTIATING = 'negotiating' PROSPECTIVE_PARTNER_UNINTERESTED = 'uninterested' PROSPECTIVE_PARTNER_PROCESSED = 'processed' @@ -27,6 +28,7 @@ PROSPECTIVE_PARTNER_STATUS = ( (PROSPECTIVE_PARTNER_REQUESTED, 'Requested (from online form)'), (PROSPECTIVE_PARTNER_ADDED, 'Added internally'), (PROSPECTIVE_PARTNER_APPROACHED, 'Approached'), + (PROSPECTIVE_PARTNER_FOLLOWED_UP, 'Followed-up'), (PROSPECTIVE_PARTNER_NEGOTIATING, 'Negotiating'), (PROSPECTIVE_PARTNER_UNINTERESTED, 'Uninterested'), (PROSPECTIVE_PARTNER_PROCESSED, 'Processed into Partner'), diff --git a/partners/migrations/0038_auto_20171012_0948.py b/partners/migrations/0038_auto_20171012_0948.py new file mode 100644 index 0000000000000000000000000000000000000000..ca52c993eb6f79d641373ffb129869355338f95a --- /dev/null +++ b/partners/migrations/0038_auto_20171012_0948.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-10-12 07:48 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('partners', '0037_merge_20171009_2000'), + ] + + operations = [ + migrations.AlterField( + model_name='prospectivepartner', + name='status', + field=models.CharField(choices=[('requested', 'Requested (from online form)'), ('added', 'Added internally'), ('approached', 'Approached'), ('followuped', 'Followed-up'), ('negotiating', 'Negotiating'), ('uninterested', 'Uninterested'), ('processed', 'Processed into Partner')], default='added', max_length=32), + ), + ] diff --git a/partners/templatetags/partners_extras.py b/partners/templatetags/partners_extras.py index 6ad6a981314dbac1435dddc2f84adf951d0b9093..5bdea03aca97fa8a75cb4f9a5dcb16293ef998a7 100644 --- a/partners/templatetags/partners_extras.py +++ b/partners/templatetags/partners_extras.py @@ -5,7 +5,8 @@ from ..constants import PROSPECTIVE_PARTNER_REQUESTED,\ PROSPECTIVE_PARTNER_APPROACHED,\ PROSPECTIVE_PARTNER_NEGOTIATING,\ PROSPECTIVE_PARTNER_UNINTERESTED,\ - PROSPECTIVE_PARTNER_PROCESSED + PROSPECTIVE_PARTNER_PROCESSED,\ + PROSPECTIVE_PARTNER_FOLLOWED_UP register = template.Library() @@ -25,4 +26,6 @@ def partnerstatuscolor(status): color = '#ee0000' elif status == PROSPECTIVE_PARTNER_PROCESSED: color = '#32cd32' + elif status == PROSPECTIVE_PARTNER_FOLLOWED_UP: + color = '#d2e3f6' return color diff --git a/partners/urls.py b/partners/urls.py index b7d4e86380e830a36c026b713008e9b3349a29cb..a4ca9e619da3b462aed692fca659be4e5893aec6 100644 --- a/partners/urls.py +++ b/partners/urls.py @@ -20,9 +20,9 @@ urlpatterns = [ views.add_prospartner_contact, name='add_prospartner_contact'), url(r'^prospects/(?P<prospartner_id>[0-9]+)/promote$', views.promote_prospartner, name='promote_prospartner'), - url(r'^prospects/(?P<prospartner_id>[0-9]+)/email_generic', + url(r'^prospects/(?P<prospartner_id>[0-9]+)/email_generic$', views.email_prospartner_generic, name='email_prospartner_generic'), - url(r'^prospects/(?P<prospartner_id>[0-9]+)/email_generic/(?P<mail>followup)', + url(r'^prospects/(?P<prospartner_id>[0-9]+)/email_generic/(?P<mail>followup)$', views.email_prospartner_generic, name='email_prospartner_generic'), url(r'^prospects/(?P<prospartner_id>[0-9]+)/events/add$', views.add_prospartner_event, name='add_prospartner_event'), diff --git a/partners/views.py b/partners/views.py index 0acab83ef34b1bc6fcc097ad37f0c589cb0e87f9..577e824c1db8ac0408a6d146cdf1a54a76470bea 100644 --- a/partners/views.py +++ b/partners/views.py @@ -4,7 +4,7 @@ from django.contrib import messages from django.contrib.auth.decorators import login_required from django.db import transaction from django.forms import modelformset_factory -from django.http import FileResponse, HttpResponse +from django.http import HttpResponse from django.shortcuts import get_object_or_404, render, reverse, redirect from django.utils import timezone @@ -14,7 +14,8 @@ from mails.views import MailEditingSubView from .constants import PROSPECTIVE_PARTNER_REQUESTED,\ PROSPECTIVE_PARTNER_APPROACHED, PROSPECTIVE_PARTNER_ADDED,\ - PROSPECTIVE_PARTNER_EVENT_REQUESTED, PROSPECTIVE_PARTNER_EVENT_EMAIL_SENT + PROSPECTIVE_PARTNER_EVENT_REQUESTED, PROSPECTIVE_PARTNER_EVENT_EMAIL_SENT,\ + PROSPECTIVE_PARTNER_FOLLOWED_UP from .models import Partner, ProspectivePartner, ProspectiveContact, ContactRequest,\ ProspectivePartnerEvent, MembershipAgreement, Contact, Institution,\ PartnersAttachment @@ -25,7 +26,6 @@ from .forms import ProspectivePartnerForm, ProspectiveContactForm,\ NewContactForm, InstitutionForm, ActivationForm, PartnerEventForm,\ MembershipAgreementForm, RequestContactForm, RequestContactFormSet,\ ProcessRequestContactForm, PartnersAttachmentFormSet, PartnersAttachmentForm -from .utils import PartnerUtils def supporting_partners(request): @@ -265,13 +265,17 @@ def add_prospartner_contact(request, prospartner_id): def email_prospartner_contact(request, contact_id, mail=None): contact = get_object_or_404(ProspectiveContact, pk=contact_id) + suffix = '' if mail == 'followup': code = 'partners_followup_mail' + suffix = ' (followup)' + new_status = PROSPECTIVE_PARTNER_FOLLOWED_UP else: code = 'partners_initial_mail' + new_status = PROSPECTIVE_PARTNER_APPROACHED mail_request = MailEditingSubView(request, mail_code=code, contact=contact) if mail_request.is_valid(): - comments = 'Email sent to %s.' % str(contact) + comments = 'Email{suffix} sent to {name}.'.format(suffix=suffix, name=contact) prospartnerevent = ProspectivePartnerEvent( prospartner=contact.prospartner, event=PROSPECTIVE_PARTNER_EVENT_EMAIL_SENT, @@ -280,8 +284,9 @@ def email_prospartner_contact(request, contact_id, mail=None): noted_by=request.user.contributor) prospartnerevent.save() if contact.prospartner.status in [PROSPECTIVE_PARTNER_REQUESTED, - PROSPECTIVE_PARTNER_ADDED]: - contact.prospartner.status = PROSPECTIVE_PARTNER_APPROACHED + PROSPECTIVE_PARTNER_ADDED, + PROSPECTIVE_PARTNER_APPROACHED]: + contact.prospartner.status = new_status contact.prospartner.save() messages.success(request, 'Email successfully sent.') @@ -296,13 +301,19 @@ def email_prospartner_contact(request, contact_id, mail=None): def email_prospartner_generic(request, prospartner_id, mail=None): prospartner = get_object_or_404(ProspectivePartner, pk=prospartner_id) + suffix = '' + if mail == 'followup': code = 'partners_followup_mail' + suffix = ' (followup)' + new_status = PROSPECTIVE_PARTNER_FOLLOWED_UP else: code = 'partners_initial_mail' + new_status = PROSPECTIVE_PARTNER_APPROACHED mail_request = MailEditingSubView(request, mail_code=code) if mail_request.is_valid(): - comments = 'Email sent to %s.' % str(mail_request.recipients_string) + comments = 'Email{suffix} sent to {name}.'.format(suffix=suffix, + name=mail_request.recipients_string) prospartnerevent = ProspectivePartnerEvent( prospartner=prospartner, event=PROSPECTIVE_PARTNER_EVENT_EMAIL_SENT, @@ -311,8 +322,9 @@ def email_prospartner_generic(request, prospartner_id, mail=None): noted_by=request.user.contributor) prospartnerevent.save() if prospartner.status in [PROSPECTIVE_PARTNER_REQUESTED, - PROSPECTIVE_PARTNER_ADDED]: - prospartner.status = PROSPECTIVE_PARTNER_APPROACHED + PROSPECTIVE_PARTNER_ADDED, + PROSPECTIVE_PARTNER_APPROACHED]: + prospartner.status = new_status prospartner.save() messages.success(request, 'Email successfully sent.') diff --git a/production/managers.py b/production/managers.py index 5bd1b5c00b0adc2df29de3e8b7c59881a4235fec..a88a6ed1cebaa7920f658f12685436416e558460 100644 --- a/production/managers.py +++ b/production/managers.py @@ -23,6 +23,9 @@ class ProductionEventManager(models.Manager): def get_my_events(self, production_user): return self.filter(noted_by=production_user) + def all_without_duration(self): + return self.filter(duration__isnull=True) + class ProofsQuerySet(models.QuerySet): def for_authors(self): diff --git a/production/templates/production/partials/production_stream_card.html b/production/templates/production/partials/production_stream_card.html index 85473b2a34db7edfd56af09298e575b9c3a9df72..1637b4bfe06682c252a2b3e733a99d74db397785 100644 --- a/production/templates/production/partials/production_stream_card.html +++ b/production/templates/production/partials/production_stream_card.html @@ -7,7 +7,7 @@ {% include 'production/partials/stream_status_changes.html' with form=status_form stream=stream %} <h3>Events</h3> - {% include 'production/partials/production_events.html' with events=stream.events.all %} + {% include 'production/partials/production_events.html' with events=stream.events.all_without_duration %} {% if "can_work_for_stream" in sub_perms and prodevent_form %} <h3>Add message to the Stream</h3> diff --git a/production/templates/production/partials/production_stream_card_completed.html b/production/templates/production/partials/production_stream_card_completed.html index 19eb76bb651c36fc534b62fcd830b29da70ae657..fd91b061844a670150a47a19464e9ceaf26227a2 100644 --- a/production/templates/production/partials/production_stream_card_completed.html +++ b/production/templates/production/partials/production_stream_card_completed.html @@ -38,7 +38,7 @@ {% block actions %} <h3>Events</h3> - {% include 'production/partials/production_events.html' with events=stream.events.all non_editable=1 %} + {% include 'production/partials/production_events.html' with events=stream.events.all_without_duration non_editable=1 %} <h3>Work Log</h3> {% include 'partials/finances/logs.html' with logs=stream.work_logs.all %} diff --git a/production/templates/production/production.html b/production/templates/production/production.html index 844922fd09730361c68469c5a446ac6493eb5201..caf432ea2b5c240ce0133606dbcd6ebb5713dd8f 100644 --- a/production/templates/production/production.html +++ b/production/templates/production/production.html @@ -67,7 +67,7 @@ </div> <div> <p class="mb-1"> - <a href="{% url 'production:stream' stream.id %}">{{ stream.submission.title }}</a><br> + <a href="{% url 'production:stream' stream.id %}" data-toggle="dynamic" data-target="#details">{{ stream.submission.title }}</a><br> <em>by {{ stream.submission.author_list }}</em> </p> <p class="card-text mb-2"> diff --git a/requirements.txt b/requirements.txt index 0cb1a60d9d08cddb4f124bfd6db4574d220c53ab..21531ce520116fba8000b6c04f2201a7bb7ee953 100644 --- a/requirements.txt +++ b/requirements.txt @@ -47,6 +47,7 @@ ithenticate-api-python==0.7 mailchimp3==2.0.15 python-dateutil==2.6.0 # Doesn't Django have this functionality built-in? -- JdW Pillow==3.4.2 # Latest version is v4.2.1; need to know about usage before upgrade. -- JdW +html2text # Possibly dead (most probably not used anymore and possibly not up-to-date packages) -- JdW (August 15th, 2017) imagesize==0.7.1 diff --git a/scipost/templates/scipost/personal_page.html b/scipost/templates/scipost/personal_page.html index 202a0041ce9d9785f111980618c3e11840d5e65d..df6434f83530092e5f3ad28a0e65b77f61e91af5 100644 --- a/scipost/templates/scipost/personal_page.html +++ b/scipost/templates/scipost/personal_page.html @@ -119,6 +119,14 @@ {# END: Scientist fields #} {% endif %} + {% if not request.user.contributor.petition_signatories.exists %} + <div class="border border-danger p-2"> + <h3 class="text-danger">Scientists, please help us out!</h3> + <p class="mb-1">If it is not listed on our Partners page, please encourage your institution (through a librarian, director, ...) to join by <a class="h3 text-blue" href="{% url 'petitions:petition' slug='join-SPB' %}">signing our petition</a>.</p> + </div> + {% endif %} + <hr> + {% if 'SciPost Administrators' in user_groups %} <h3>You are a SciPost Administrator.</h3> {% endif %} diff --git a/templates/email/SPB_petition_signature_thanks.html b/templates/email/SPB_petition_signature_thanks.html index d528bf7666449f25a968acb281be50b2ae138f78..2dd1fa74a220c2ab0aa1a70ec3557874824a49d8 100644 --- a/templates/email/SPB_petition_signature_thanks.html +++ b/templates/email/SPB_petition_signature_thanks.html @@ -1,8 +1,9 @@ <p>Many thanks for signing the petition!</p> +<p>One quick and easy way to help us further is to get your colleagues to also sign. Please consider doing this, via word-of-mouth or email!</p> <p> - If you have not done so already, you can really further help SciPost convince + One less quick but even more effective way to further help SciPost convince your institution, library and/or funding agency to become Supporting Partners - by sending a personalized email to one of their representatives; you can use our + is to send a personalized email to one of their representatives; you can use our <a href="mailto:?subject=Petition to support SciPost&body=[PLEASE FILL IN THE TO FIELD ABOVE (keeping partners@scipost.org in cc)]%0D%0A%0D%0ADear ...%0D%0A%0D%0A[PLEASE WRITE A PERSONALIZED MESSAGE]%0D%0A%0D%0AHere under, you will find basic information about SciPost and how you can support it.%0D%0A%0D%0ASincerely,%0D%0A[YOUR SIGNATURE]%0D%0A%0D%0A%0D%0A%0D%0ASciPost (https://scipost.org) is a top-quality next-generation Open Access publication portal managed by professional scientists. Its principles, ideals and implementation can be found at https://scipost.org/about and https://scipost.org/FAQ.%0D%0A%0D%0ASciPost follows a different funding model than most traditional publishers. It operates on an entirely not-for-profit basis, and charges neither subscription fees nor article processing charges; instead, its activities are financed through a cost-slashing consortial model.%0D%0A%0D%0ABy making a small financial commitment, the institutions and organizations that benefit from SciPost’s activities can become Supporting Partners. This enables SciPost to perform all of its publication-related activities, maintain its online portal and implement its long-term development plan. Details of the consortial funding scheme and how to join can be found at https://scipost.org/partners or by emailing partners@scipost.org.%0D%0A&cc=partners@scipost.org">template</a> as a start.</p> <p> You can also point them towards details of our consortial funding scheme on our <a href="https://scipost.org/partners">Partners page</a>, and our <a href="https://scipost.org/static/scipost/SPB/SciPost_Supporting_Partners_Board_Prospectus.pdf">one-page Prospectus</a> summarizing the scheme, which is expounded in detail in the draft <a href="https://scipost.org/static/scipost/SPB/SciPost_Supporting_Partner_Agreement.pdf">Partner Agreement</a>. diff --git a/templates/email/SPB_petition_signature_thanks.txt b/templates/email/SPB_petition_signature_thanks.txt index ad8c0002e889cf3031538cbc1f9f1494e80a41ab..ef40b7c4810ad62132a22799193cbe9523a3a78d 100644 --- a/templates/email/SPB_petition_signature_thanks.txt +++ b/templates/email/SPB_petition_signature_thanks.txt @@ -1,7 +1,5 @@ Many thanks for signing the petition!\n\n -If you have not done so already, you can really further help SciPost convince -your institution, library and/or funding agency to become Supporting Partners -by sending a personalized email to one of their representatives; we have a -handy email template for you to use at https://scipost.org/partners/.\n\n +One quick and easy way to help us further is to get your colleagues to also sign. We'd be grateful if you considered doing this, via word-of-mouth or email!\n\n +One less quick but even more effective way to further help SciPost convince your institution, library and/or funding agency to become Supporting Partners is to send a personalized email to one of their representatives; we have a handy email template for you to use at https://scipost.org/partners/.\n\n You can also point them to our prospectus and draft agreement on that same page.\n\nWe are very grateful for your help.\n\nThe SciPost Team