Source code for theses.forms

__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"


from django import forms
from django.core.mail import EmailMessage
from django.template.loader import render_to_string

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div
from crispy_bootstrap5.bootstrap5 import FloatingField

from scipost.models import Contributor
from scipost.utils import build_absolute_uri_using_site
from common.utils import get_current_domain

from .models import ThesisLink
from .helpers import past_years


[docs]class BaseRequestThesisLinkForm(forms.ModelForm):
[docs] class Meta: model = ThesisLink fields = [ "type", "acad_field", "specialties", "approaches", "title", "author", "supervisor", "institution", "defense_date", "pub_link", "abstract", ] widgets = { "defense_date": forms.SelectDateWidget(years=past_years(50)), "pub_link": forms.TextInput(attrs={"placeholder": "Full URL"}), }
[docs]class RequestThesisLinkForm(BaseRequestThesisLinkForm): def __init__(self, *args, **kwargs): self.request = kwargs.pop("request") self.user = self.request.user super(RequestThesisLinkForm, self).__init__(*args, **kwargs)
[docs] def save(self, *args, **kwargs): """Prefill instance before save""" self.instance.requested_by = Contributor.objects.get(user=self.user) return super(RequestThesisLinkForm, self).save(*args, **kwargs)
[docs]class VetThesisLinkForm(BaseRequestThesisLinkForm): MODIFY = 0 ACCEPT = 1 REFUSE = 2 THESIS_ACTION_CHOICES = ( (MODIFY, "modify"), (ACCEPT, "accept"), (REFUSE, "refuse (give reason below)"), ) EMPTY_CHOICE = 0 ALREADY_EXISTS = 1 LINK_DOES_NOT_WORK = 2 THESIS_REFUSAL_CHOICES = ( (EMPTY_CHOICE, "---"), (ALREADY_EXISTS, "A link to this thesis already exists"), (LINK_DOES_NOT_WORK, "The external link to this thesis does not work"), ) action_option = forms.ChoiceField( widget=forms.RadioSelect, choices=THESIS_ACTION_CHOICES, required=True, label="Action", ) refusal_reason = forms.ChoiceField(choices=THESIS_REFUSAL_CHOICES, required=False) justification = forms.CharField( widget=forms.Textarea(attrs={"rows": 5, "cols": 40}), label="Justification (optional)", required=False, ) def __init__(self, *args, **kwargs): super(VetThesisLinkForm, self).__init__(*args, **kwargs) self.order_fields(["action_option", "refusal_reason", "justification"])
[docs] def vet_request(self, thesislink, user): mail_params = { "vocative_title": thesislink.requested_by.profile.get_title_display(), "thesislink": thesislink, "full_url": build_absolute_uri_using_site(thesislink.get_absolute_url()), } action = int(self.cleaned_data["action_option"]) if action == VetThesisLinkForm.ACCEPT or action == VetThesisLinkForm.MODIFY: thesislink.vetted = True thesislink.vetted_by = Contributor.objects.get(user=user) thesislink.save() subject_line = "SciPost Thesis Link activated" if action == VetThesisLinkForm.ACCEPT: message_plain = render_to_string( "theses/thesislink_accepted.txt", mail_params ) elif action == VetThesisLinkForm.MODIFY: message_plain = render_to_string( "theses/thesislink_modified.txt", mail_params ) elif action == VetThesisLinkForm.REFUSE: refusal_reason = int(self.cleaned_data["refusal_reason"]) refusal_reason = dict(self.fields["refusal_reason"].choices)[refusal_reason] mail_params["refusal_reason"] = refusal_reason mail_params["justification"] = self.cleaned_data["justification"] message_plain = render_to_string( "theses/thesislink_refused.txt", mail_params ) subject_line = "SciPost Thesis Link" thesislink.delete() domain = get_current_domain() email = EmailMessage( subject_line, message_plain, f"SciPost Theses <theses@{domain}>", [thesislink.requested_by.user.email], [f"theses@{domain}"], reply_to=[f"theses@{domain}"], ).send(fail_silently=False)
[docs]class ThesisLinkSearchForm(forms.Form): author = forms.CharField(max_length=100, required=False, label="Author") title_keyword = forms.CharField(max_length=100, label="Title", required=False) abstract_keyword = forms.CharField( max_length=1000, required=False, label="Abstract" ) supervisor = forms.CharField(max_length=100, required=False, label="Supervisor")
[docs]class ThesisSearchForm(forms.Form): author = forms.CharField(max_length=100, required=False, label="Author") title = forms.CharField(max_length=100, label="Title", required=False) abstract = forms.CharField( max_length=1000, required=False, label="Abstract" ) supervisor = forms.CharField(max_length=100, required=False, label="Supervisor") def __init__(self, *args, **kwargs): self.acad_field_slug = kwargs.pop("acad_field_slug") self.specialty_slug = kwargs.pop("specialty_slug") super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.layout = Layout( Div( FloatingField("author"), FloatingField("title"), FloatingField("abstract"), FloatingField("supervisor"), ), )
[docs] def search_results(self): """Return all ThesisLink objects fitting search""" theses = ThesisLink.objects.vetted() if self.acad_field_slug and self.acad_field_slug != "all": theses = theses.filter(acad_field__slug=self.acad_field_slug) if self.specialty_slug and self.specialty_slug != "all": theses = theses.filter( specialties__slug=self.specialty_slug ) if hasattr(self, "cleaned_data"): if "title" in self.cleaned_data: theses = theses.filter( title__icontains=self.cleaned_data["title"], ) len(theses) if "abstract" in self.cleaned_data: theses = theses.filter( abstract__icontains=self.cleaned_data["abstract"], ) if "author" in self.cleaned_data: theses = theses.filter( author__icontains=self.cleaned_data["author"], ) if "supervisor" in self.cleaned_data: theses = theses.filter( supervisor__icontains=self.cleaned_data["supervisor"], ) return theses.order_by("-defense_date")