From fad818069cee13ef078561b80fbaaa3d6138a0f5 Mon Sep 17 00:00:00 2001 From: Jorran Wit <jorrandewit@outlook.com> Date: Fri, 23 Dec 2016 23:26:54 +0100 Subject: [PATCH] Move vet_commentary_request logic to form Logic from vet_commentary_request has been moved to the VetCommentaryForm form. Further moved some code to improve DRY. --- commentaries/forms.py | 102 +++++++++++++++++++++++++++---- commentaries/views.py | 135 +++++++++++++++++++++--------------------- 2 files changed, 161 insertions(+), 76 deletions(-) diff --git a/commentaries/forms.py b/commentaries/forms.py index f0dcdf3a3..acf9558fa 100644 --- a/commentaries/forms.py +++ b/commentaries/forms.py @@ -5,17 +5,15 @@ from .models import Commentary from scipost.models import Contributor -COMMENTARY_ACTION_CHOICES = ( - (0, 'modify'), - (1, 'accept'), - (2, 'refuse (give reason below)'), - ) - +REFUSAL_EMPTY = 0 +REFUSAL_PAPER_EXISTS = -1 +REFUSAL_UNTRACEBLE = -2 +REFUSAL_ARXIV_EXISTS = -3 COMMENTARY_REFUSAL_CHOICES = ( - (0, '-'), - (-1, 'a commentary on this paper already exists'), - (-2, 'this paper cannot be traced'), - (-3, 'there exists a more revent version of this arXiv preprint'), + (REFUSAL_EMPTY, '-'), + (REFUSAL_PAPER_EXISTS, 'a commentary on this paper already exists'), + (REFUSAL_UNTRACEBLE, 'this paper cannot be traced'), + (REFUSAL_ARXIV_EXISTS, 'there exists a more revent version of this arXiv preprint'), ) commentary_refusal_dict = dict(COMMENTARY_REFUSAL_CHOICES) @@ -32,6 +30,7 @@ class IdentifierToQueryForm(forms.Form): class RequestCommentaryForm(forms.ModelForm): + """Create new valid Commetary by user request""" existing_commentary = None class Meta: @@ -54,6 +53,7 @@ class RequestCommentaryForm(forms.ModelForm): self.fields['pub_abstract'].widget.attrs.update({'cols': 100}) def clean(self, *args, **kwargs): + """Check if form is valid and contains an unique identifier""" cleaned_data = super(RequestCommentaryForm, self).clean(*args, **kwargs) # Either Arxiv-ID or DOI is given @@ -92,6 +92,26 @@ class RequestCommentaryForm(forms.ModelForm): class VetCommentaryForm(forms.Form): + """Process an unvetted Commentary request. + + This form will provide fields to let the user + process a Commentary that is unvetted. On success, + the Commentary is either accepted or deleted from + the database. + + Keyword arguments: + commentary_id -- the Commentary.id to process (required) + user -- User instance of the vetting user (required) + + """ + ACTION_MODIFY = 0 + ACTION_ACCEPT = 1 + ACTION_REFUSE = 2 + COMMENTARY_ACTION_CHOICES = ( + (ACTION_MODIFY, 'modify'), + (ACTION_ACCEPT, 'accept'), + (ACTION_REFUSE, 'refuse (give reason below)'), + ) action_option = forms.ChoiceField(widget=forms.RadioSelect, choices=COMMENTARY_ACTION_CHOICES, required=True, label='Action') @@ -99,6 +119,68 @@ class VetCommentaryForm(forms.Form): email_response_field = forms.CharField(widget=forms.Textarea( attrs={'rows': 5, 'cols': 40}), label='Justification (optional)', required=False) + def __init__(self, *args, **kwargs): + """Pop and save keyword arguments if set, return form instance""" + self.commentary_id = kwargs.pop('commentary_id', None) + self.user = kwargs.pop('user', None) + self.is_cleaned = False + return super(VetCommentaryForm, self).__init__(*args, **kwargs) + + def clean(self, *args, **kwargs): + """Check valid form and keyword arguments given""" + cleaned_data = super(VetCommentaryForm, self).clean(*args, **kwargs) + + # Check valid `commentary_id` + if not self.commentary_id: + self.add_error(None, 'No `commentary_id` provided') + return cleaned_data + else: + self.commentary = Commentary.objects.get(pk=self.commentary_id) + + # Check valid `user` + if not self.user: + self.add_error(None, 'No `user` provided') + return cleaned_data + + self.is_cleaned = True + return cleaned_data + + def _form_is_cleaned(self): + """Raise ValueError if form isn't validated""" + if not self.is_cleaned: + raise ValueError(('VetCommentaryForm could not be processed ' + 'because the data didn\'t validate')) + + def get_commentary(self): + """Return Commentary if available""" + self._form_is_cleaned() + return self.commentary + + def process_commentary(self): + """Vet the commentary or delete it from the database""" + self._form_is_cleaned() + + if self.commentary_is_accepted(): + self.commentary.vetted = True + self.commentary.vetted_by = Contributor.objects.get(user=self.user) + self.commentary.save() + return self.commentary + elif self.commentary_is_modified() or self.commentary_is_refused(): + self.commentary.delete() + return None + + def commentary_is_accepted(self): + self._form_is_cleaned() + return int(self.cleaned_data['action_option']) == self.ACTION_ACCEPT + + def commentary_is_modified(self): + self._form_is_cleaned() + return int(self.cleaned_data['action_option']) == self.ACTION_MODIFY + + def commentary_is_refused(self): + self._form_is_cleaned() + return int(self.cleaned_data['action_option']) == self.ACTION_REFUSE + class CommentarySearchForm(forms.Form): """Search for Commentary specified by user""" diff --git a/commentaries/views.py b/commentaries/views.py index 506fd838f..015d35798 100644 --- a/commentaries/views.py +++ b/commentaries/views.py @@ -140,7 +140,7 @@ def prefill_using_DOI(request): @permission_required('scipost.can_request_commentary_pages', raise_exception=True) def prefill_using_identifier(request): - """ Probes arXiv with the identifier, to pre-fill the form. """ + """Probes arXiv with the identifier, to pre-fill the form""" if request.method == "POST": identifierform = IdentifierToQueryForm(request.POST) if identifierform.is_valid(): @@ -226,6 +226,7 @@ def prefill_using_identifier(request): @permission_required('scipost.can_vet_commentary_requests', raise_exception=True) def vet_commentary_requests(request): + """Show the first commentary thats awaiting vetting""" contributor = Contributor.objects.get(user=request.user) commentary_to_vet = Commentary.objects.awaiting_vetting().first() # only handle one at a time form = VetCommentaryForm() @@ -235,74 +236,76 @@ def vet_commentary_requests(request): @permission_required('scipost.can_vet_commentary_requests', raise_exception=True) def vet_commentary_request_ack(request, commentary_id): if request.method == 'POST': - form = VetCommentaryForm(request.POST) - commentary = Commentary.objects.get(pk=commentary_id) + form = VetCommentaryForm(request.POST, user=request.user, commentary_id=commentary_id) if form.is_valid(): - if form.cleaned_data['action_option'] == '1': - # accept the commentary as is - commentary.vetted = True - commentary.vetted_by = Contributor.objects.get(user=request.user) - commentary.latest_activity = timezone.now() - commentary.save() - email_text = ('Dear ' + title_dict[commentary.requested_by.title] + ' ' - + commentary.requested_by.user.last_name - + ', \n\nThe Commentary Page you have requested, ' - 'concerning publication with title ' - + commentary.pub_title + ' by ' + commentary.author_list - + ', has been activated at https://scipost.org/commentary/' - + str(commentary.arxiv_or_DOI_string) - + '. You are now welcome to submit your comments.' - '\n\nThank you for your contribution, \nThe SciPost Team.') - emailmessage = EmailMessage('SciPost Commentary Page activated', email_text, - 'SciPost commentaries <commentaries@scipost.org>', - [commentary.requested_by.user.email], - ['commentaries@scipost.org'], - reply_to=['commentaries@scipost.org']) - emailmessage.send(fail_silently=False) - elif form.cleaned_data['action_option'] == '0': - # re-edit the form starting from the data provided - form2 = RequestCommentaryForm(initial={'pub_title': commentary.pub_title, - 'arxiv_link': commentary.arxiv_link, - 'pub_DOI_link': commentary.pub_DOI_link, - 'author_list': commentary.author_list, - 'pub_date': commentary.pub_date, - 'pub_abstract': commentary.pub_abstract}) - commentary.delete() - email_text = ('Dear ' + title_dict[commentary.requested_by.title] + ' ' - + commentary.requested_by.user.last_name - + ', \n\nThe Commentary Page you have requested, ' - 'concerning publication with title ' + commentary.pub_title - + ' by ' + commentary.author_list - + ', has been activated (with slight modifications to your submitted details).' - ' You are now welcome to submit your comments.' - '\n\nThank you for your contribution, \nThe SciPost Team.') - emailmessage = EmailMessage('SciPost Commentary Page activated', email_text, - 'SciPost commentaries <commentaries@scipost.org>', - [commentary.requested_by.user.email], - ['commentaries@scipost.org'], - reply_to=['commentaries@scipost.org']) - emailmessage.send(fail_silently=False) - context = {'form': form2 } - return render(request, 'commentaries/request_commentary.html', context) - elif form.cleaned_data['action_option'] == '2': - # the commentary request is simply rejected + # Get commentary + commentary = form.get_commentary() + if form.commentary_is_accepted(): + # Accept the commentary as is + email_args = ( + 'SciPost Commentary Page activated', + ('Dear ' + title_dict[commentary.requested_by.title] + ' ' + + commentary.requested_by.user.last_name + + ', \n\nThe Commentary Page you have requested, ' + 'concerning publication with title ' + + commentary.pub_title + ' by ' + commentary.author_list + + ', has been activated at https://scipost.org/commentary/' + + str(commentary.arxiv_or_DOI_string) + + '. You are now welcome to submit your comments.' + '\n\nThank you for your contribution, \nThe SciPost Team.') + ) + elif form.commentary_is_modified(): + # Re-edit the form starting from the data provided + email_args = ( + 'SciPost Commentary Page activated', + ('Dear ' + title_dict[commentary.requested_by.title] + ' ' + + commentary.requested_by.user.last_name + + ', \n\nThe Commentary Page you have requested, ' + 'concerning publication with title ' + commentary.pub_title + + ' by ' + commentary.author_list + + ', has been activated (with slight modifications to your submitted details).' + ' You are now welcome to submit your comments.' + '\n\nThank you for your contribution, \nThe SciPost Team.') + ) + + request_commentary_form = RequestCommentaryForm(initial={ + 'pub_title': commentary.pub_title, + 'arxiv_link': commentary.arxiv_link, + 'pub_DOI_link': commentary.pub_DOI_link, + 'author_list': commentary.author_list, + 'pub_date': commentary.pub_date, + 'pub_abstract': commentary.pub_abstract + }) + elif form.commentary_is_refused(): + # The commentary request is simply rejected email_text = ('Dear ' + title_dict[commentary.requested_by.title] + ' ' - + commentary.requested_by.user.last_name - + ', \n\nThe Commentary Page you have requested, ' - 'concerning publication with title ' - + commentary.pub_title + ' by ' + commentary.author_list - + ', has not been activated for the following reason: ' - + commentary_refusal_dict[int(form.cleaned_data['refusal_reason'])] - + '.\n\nThank you for your interest, \nThe SciPost Team.') + + commentary.requested_by.user.last_name + + ', \n\nThe Commentary Page you have requested, ' + 'concerning publication with title ' + + commentary.pub_title + ' by ' + commentary.author_list + + ', has not been activated for the following reason: ' + + commentary_refusal_dict[int(form.cleaned_data['refusal_reason'])] + + '.\n\nThank you for your interest, \nThe SciPost Team.') + if form.cleaned_data['email_response_field']: - email_text += '\n\nFurther explanations: ' + form.cleaned_data['email_response_field'] - emailmessage = EmailMessage('SciPost Commentary Page activated', email_text, - 'SciPost commentaries <commentaries@scipost.org>', - [commentary.requested_by.user.email], - ['commentaries@scipost.org'], - reply_to=['comentaries@scipost.org']) - emailmessage.send(fail_silently=False) - commentary.delete() + email_text += '\n\nFurther explanations: ' + email_text += form.cleaned_data['email_response_field'] + + email_args = ( + 'SciPost Commentary Page activated', + email_text + ) + + # Send email and process form + email_args += ([commentary.requested_by.user.email], ['commentaries@scipost.org'],) + emailmessage = EmailMessage(*email_args, reply_to=['commentaries@scipost.org']) + emailmessage.send(fail_silently=False) + commentary = form.process_commentary() + + if form.commentary_is_modified(): + # For a modified commentary, redirect to request_commentary_form + context = {'form': request_commentary_form} + return render(request, 'commentaries/request_commentary.html', context) context = {'ack_header': 'SciPost Commentary request vetted.', 'followup_message': 'Return to the ', -- GitLab