SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit 3a57bf89 authored by Jorran de Wit's avatar Jorran de Wit
Browse files

Merged in commentaries/wip-jorran (pull request #2)

Merge Commentaries/wip-jorran
parents 88808837 f5d1be09
No related branches found
No related tags found
No related merge requests found
......@@ -12,12 +12,14 @@ https://docs.djangoproject.com/en/1.8/ref/settings/
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
import json
from django.utils.translation import ugettext_lazy as _
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
host_settings_path = os.path.join(os.path.dirname(BASE_DIR),"scipost-host-settings.json")
host_settings_path = os.path.join(os.path.dirname(BASE_DIR), "scipost-host-settings.json")
host_settings = json.load(open(host_settings_path))
# Quick-start development settings - unsuitable for production
......@@ -109,6 +111,7 @@ MATHJAX_CONFIG_DATA = {
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
......@@ -129,6 +132,7 @@ TEMPLATES = [
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.template.context_processors.i18n',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'scipost.context_processors.searchform',
......@@ -159,7 +163,12 @@ DATABASES = {
# https://docs.djangoproject.com/en/1.8/topics/i18n/
LANGUAGE_CODE = 'en-us'
LANGUAGES = (
('en', _('English')),
)
LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale'),
)
TIME_ZONE = 'CET'
USE_I18N = True
......
# -*- coding: utf-8 -*-
# Generated by Django 1.10.3 on 2016-12-19 20:26
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('comments', '0004_auto_20161212_1931'),
('comments', '0004_auto_20161213_1208'),
]
operations = [
]
import factory
class FormFactory(factory.Factory):
class Meta:
strategy = factory.BUILD_STRATEGY
@classmethod
def _build(cls, model_class, *args, **kwargs):
return model_class(kwargs)
......@@ -26,6 +26,7 @@
<body>
{% include 'scipost/header.html' %}
{% include 'scipost/navbar.html' %}
{% include 'scipost/messages.html' %}
{% block bodysup %}
{% endblock bodysup %}
......
{% for message in messages %}
<div class="alert {{ message.tags }} alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
{{ message }}
</div>
{% endfor %}
acknowledge_request_thesis_link = "Thank you for your request for a Thesis Link. Your request will soon be handled by an editor"
import factory
from .models import ThesisLink
from common.helpers.factories import FormFactory
from scipost.factories import ContributorFactory
from .models import ThesisLink
from .forms import VetThesisLinkForm
class ThesisLinkFactory(factory.django.DjangoModelFactory):
class Meta:
......@@ -9,7 +13,7 @@ class ThesisLinkFactory(factory.django.DjangoModelFactory):
requested_by = factory.SubFactory(ContributorFactory)
type = ThesisLink.MASTER_THESIS
title = factory.Sequence(lambda n: "thesis {0}".format(n))
title = factory.Faker('bs')
pub_link = factory.Faker('uri')
author = factory.Faker('name')
supervisor = factory.Faker('name')
......@@ -17,3 +21,11 @@ class ThesisLinkFactory(factory.django.DjangoModelFactory):
defense_date = factory.Faker('date_time_this_century')
abstract = factory.Faker('text')
domain = 'ET'
class VetThesisLinkFormFactory(FormFactory):
class Meta:
model = VetThesisLinkForm
action_option = VetThesisLinkForm.ACCEPT
# justification = factory.Faker('lorem')
......@@ -3,18 +3,6 @@ from django import forms
from .models import *
from .helpers import past_years
THESIS_ACTION_CHOICES = (
(0, 'modify'),
(1, 'accept'),
(2, 'refuse (give reason below)'),
)
THESIS_REFUSAL_CHOICES = (
(0, '-'),
(-1, 'a link to this thesis already exists'),
(-2, 'the external link to this thesis does not work'),
)
class RequestThesisLinkForm(forms.ModelForm):
class Meta:
......@@ -29,13 +17,35 @@ class RequestThesisLinkForm(forms.ModelForm):
class VetThesisLinkForm(forms.Form):
action_option = forms.ChoiceField(widget=forms.RadioSelect,
choices=THESIS_ACTION_CHOICES,
required=True, label='Action')
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)
email_response_field = forms.CharField(widget=forms.Textarea(
justification = forms.CharField(widget=forms.Textarea(
attrs={'rows': 5, 'cols': 40}), label='Justification (optional)', required=False)
def vet_request(self, thesis_link):
print(self.cleaned_data)
if self.cleaned_data['action_option'] == VetThesisLinkForm.ACCEPT:
print('hoi')
class ThesisLinkSearchForm(forms.Form):
author = forms.CharField(max_length=100, required=False, label="Author")
......
......@@ -22,7 +22,7 @@
<p>{{ thesislink_to_vet.abstract }}</p>
</div>
<div class="col-4">
<form action="{% url 'theses:vet_thesislink_request_ack' thesislink_id=thesislink_to_vet.id %}" method="post">
<form method="post">
{% csrf_token %}
{{ form.as_ul }}
<input type="submit" value="Submit" />
......
......@@ -2,8 +2,8 @@ import factory
from django.test import TestCase
from .factories import ThesisLinkFactory
from .forms import RequestThesisLinkForm
from .factories import ThesisLinkFactory, VetThesisLinkFormFactory
from .forms import RequestThesisLinkForm, VetThesisLinkForm
from common.helpers import model_form_data
......@@ -24,3 +24,21 @@ class TestRequestThesisLink(TestCase):
form = RequestThesisLinkForm(form_data)
form.is_valid()
self.assertEqual(form.errors['domain'], ['This field is required.'])
class TestVetThesisLinkRequests(TestCase):
fixtures = ['permissions', 'groups']
def test_thesislink_gets_vetted_when_accepted(self):
thesis_link = ThesisLinkFactory()
form = VetThesisLinkFormFactory()
form.is_valid()
form.vet_request(thesis_link)
self.assertTrue(thesis_link.vetted)
def test_thesislink_is_not_vetted_when_refused(self):
thesis_link = ThesisLinkFactory()
form = VetThesisLinkFormFactory(action_option=VetThesisLinkForm.REFUSE)
form.is_valid()
form.vet_request(thesis_link)
self.assertFalse(thesis_link.vetted)
import re
from django.core.exceptions import PermissionDenied
from django.test import TestCase, RequestFactory
from django.test.client import Client
from django.contrib.auth.models import AnonymousUser
from django.contrib.auth.models import Group
from django.urls import reverse
from .views import RequestThesisLink
from scipost.factories import UserFactory
from .factories import ThesisLinkFactory
from .views import RequestThesisLink, VetThesisLinkRequests
from scipost.factories import UserFactory, ContributorFactory
from .factories import ThesisLinkFactory, VetThesisLinkFormFactory
from .models import ThesisLink
......@@ -25,18 +28,63 @@ class TestRequestThesisLink(TestCase):
def setUp(self):
self.client = Client()
self.target = reverse('theses:request_thesislink')
def test_response_when_not_logged_in(self):
'''A visitor that is not logged in cannot view this page.'''
response = self.client.get(reverse('theses:request_thesislink'))
response = self.client.get(self.target)
self.assertEqual(response.status_code, 403)
def test_response_when_logged_in(self):
request = RequestFactory().get(reverse('theses:request_thesislink'))
request = RequestFactory().get(self.target)
request.user = UserFactory()
response = RequestThesisLink.as_view()(request)
self.assertEqual(response.status_code, 200)
def test_redirects_to_acknowledgement_page(self):
response = self.client.post(reverse('theses:request_thesislink'), {}, follow=True)
self.assertRedirects(response, reverse('scipost:acknowledgement'))
class TestVetThesisLinkRequests(TestCase):
fixtures = ['groups', 'permissions']
def setUp(self):
self.client = Client()
self.target = reverse('theses:vet_thesislink_requests')
def test_response_when_not_logged_in(self):
response = self.client.get(self.target)
self.assertEqual(response.status_code, 403)
def test_response_regular_contributor(self):
'''
A Contributor needs to be in the Vetting Editors group to be able to
vet submitted thesis links.
'''
# Create ThesisLink to vet.
ThesisLinkFactory()
request = RequestFactory().get(self.target)
user = UserFactory()
request.user = user
self.assertRaises(
PermissionDenied, VetThesisLinkRequests.as_view(), request)
def test_response_vetting_editor(self):
# Create ThesisLink to vet.
ThesisLinkFactory()
request = RequestFactory().get(self.target)
user = UserFactory()
user.groups.add(Group.objects.get(name="Vetting Editors"))
request.user = user
response = VetThesisLinkRequests.as_view()(request)
self.assertEqual(response.status_code, 200)
def test_thesislink_is_vetted_by_correct_contributor(self):
# TODO: how to make sure we are vetting the right thesis link?
contributor = ContributorFactory()
contributor.user.groups.add(Group.objects.get(name="Vetting Editors"))
post_data = VetThesisLinkFormFactory().data
request = RequestFactory().post(self.target, post_data)
request.user = contributor.user
response = VetThesisLinkRequests.as_view()(request)
self.assertTrue(False)
......@@ -9,7 +9,7 @@ urlpatterns = [
url(r'^browse/(?P<discipline>[a-z]+)/(?P<nrweeksback>[0-9]+)/$', views.browse, name='browse'),
url(r'^(?P<thesislink_id>[0-9]+)/$', views.thesis_detail, name='thesis'),
url(r'^request_thesislink$', views.RequestThesisLink.as_view(), name='request_thesislink'),
url(r'^vet_thesislink_requests$', views.vet_thesislink_requests,
url(r'^vet_thesislink_requests$', views.VetThesisLinkRequests.as_view(),
name='vet_thesislink_requests'),
url(r'^vet_thesislink_request_ack/(?P<thesislink_id>[0-9]+)$',
views.vet_thesislink_request_ack, name='vet_thesislink_request_ack'),
......
......@@ -5,12 +5,13 @@ from django.shortcuts import get_object_or_404, render
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.models import User
from django.contrib import messages
from django.core.mail import EmailMessage
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse, reverse_lazy
from django.http import HttpResponse, HttpResponseRedirect
from django.views.decorators.csrf import csrf_protect
from django.db.models import Avg
from django.views.generic.edit import CreateView
from django.views.generic.edit import CreateView, FormView
from django.utils.decorators import method_decorator
from .models import *
......@@ -33,25 +34,43 @@ title_dict = dict(TITLE_CHOICES) # Convert titles for use in emails
class RequestThesisLink(CreateView):
form_class = RequestThesisLinkForm
template_name = 'theses/request_thesislink.html'
success_url = ''
success_url = reverse_lazy('scipost:personal_page')
def form_valid(self, form):
context = {'ack_header': 'Thank you for your request for a Thesis Link',
'ack_message': 'Your request will soon be handled by an Editor. ',
'followup_message': 'Return to your ',
'followup_link': reverse('scipost:personal_page'),
'followup_link_label': 'personal page'}
return render(self.request, 'scipost/acknowledgement.html', context)
messages.add_message(self.request, messages.SUCCESS,
strings.acknowledge_request_thesis_link)
return super(RequestThesisLink, self).form_valid(form)
@permission_required('scipost.can_vet_thesislink_requests', raise_exception=True)
def vet_thesislink_requests(request):
contributor = Contributor.objects.get(user=request.user)
thesislink_to_vet = ThesisLink.objects.filter(
vetted=False).first() # only handle one at a time
form = VetThesisLinkForm()
context = {'contributor': contributor, 'thesislink_to_vet': thesislink_to_vet, 'form': form}
return render(request, 'theses/vet_thesislink_requests.html', context)
@method_decorator(permission_required(
'scipost.can_vet_thesislink_requests', raise_exception=True), name='dispatch')
class VetThesisLinkRequests(FormView):
form_class = VetThesisLinkForm
template_name = 'theses/vet_thesislink_requests.html'
# TODO: not right yet
success_url = reverse_lazy('theses:vet_thesislink_requests')
def get_context_data(self, **kwargs):
context = super(VetThesisLinkRequests, self).get_context_data(**kwargs)
context['thesislink_to_vet'] = self.thesislink_to_vet()
return context
def thesislink_to_vet(self):
return ThesisLink.objects.filter(vetted=False).first()
def form_valid(self, form):
form.vet_request(self.thesislink_to_vet())
return super(VetThesisLinkRequests, self).form_valid(form)
# @permission_required('scipost.can_vet_thesislink_requests', raise_exception=True)
# def vet_thesislink_requests(request):
# contributor = Contributor.objects.get(user=request.user)
# thesislink_to_vet = ThesisLink.objects.filter(
# vetted=False).first() # only handle one at a time
# form = VetThesisLinkForm()
# context = {'contributor': contributor, 'thesislink_to_vet': thesislink_to_vet, 'form': form}
# return render(request, 'theses/vet_thesislink_requests.html', context)
@permission_required('scipost.can_vet_thesislink_requests', raise_exception=True)
......@@ -111,9 +130,9 @@ def vet_thesislink_request_ack(request, thesislink_id):
+ ', has not been activated for the following reason: '
+ form.cleaned_data['refusal_reason']
+ '.\n\nThank you for your interest, \nThe SciPost Team.')
if form.cleaned_data['email_response_field']:
if form.cleaned_data['justification']:
email_text += '\n\nFurther explanations: ' + \
form.cleaned_data['email_response_field']
form.cleaned_data['justification']
emailmessage = EmailMessage('SciPost Thesis Link', email_text,
'SciPost Theses <theses@scipost.org>',
[thesislink.requested_by.user.email],
......@@ -208,17 +227,16 @@ def thesis_detail(request, thesislink_id):
new_comment.save()
author.nr_comments = Comment.objects.filter(author=author).count()
author.save()
#request.session['thesislink_id'] = thesislink_id
#return HttpResponseRedirect(reverse('comments:comment_submission_ack'))
context = {'ack_header': 'Thank you for contributing a Comment.',
'ack_message': 'It will soon be vetted by an Editor.',
'followup_message': 'Back to the ',
'followup_link': reverse(
'theses:thesis',
kwargs={'thesislink_id': newcomment.thesislink.id}
),
'followup_link_label': ' Thesis Link page you came from'
}
context = {
'ack_header': 'Thank you for contributing a Comment.',
'ack_message': 'It will soon be vetted by an Editor.',
'followup_message': 'Back to the ',
'followup_link': reverse(
'theses:thesis',
kwargs={'thesislink_id': new_comment.thesislink.id}
),
'followup_link_label': ' Thesis Link page you came from'
}
return render(request, 'scipost/acknowledgement.html', context)
else:
form = CommentForm()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment