import traceback
import logging
+from django.contrib import messages
from django.core import serializers
+from django.core.exceptions import ValidationError
from django.forms.formsets import formset_factory
+from karmaworld.apps.courses.forms import CourseForm
from karmaworld.apps.courses.models import Course
from karmaworld.apps.notes.search import SearchIndex
+from karmaworld.apps.quizzes.create_quiz import quiz_from_keywords
from karmaworld.apps.quizzes.forms import KeywordForm
from karmaworld.apps.quizzes.models import Keyword
+from karmaworld.apps.quizzes.tasks import submit_extract_keywords_hit, get_extract_keywords_results
from karmaworld.apps.users.models import NoteKarmaEvent
from karmaworld.utils.ajax_utils import *
-from django.http import HttpResponse, HttpResponseBadRequest
-from django.views.generic import DetailView, ListView
+from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
+from django.views.generic import DetailView, ListView, TemplateView
from django.views.generic import FormView
from django.views.generic import View
from django.views.generic.detail import SingleObjectMixin
-from karmaworld.apps.notes.models import Note
-from karmaworld.apps.notes.forms import NoteForm
+from karmaworld.apps.notes.models import Note, KEYWORD_MTURK_THRESHOLD
+from karmaworld.apps.notes.forms import NoteForm, NoteDeleteForm
logger = logging.getLogger(__name__)
USER_PROFILE_FLAGS_FIELD = 'flagged_notes'
+def note_page_context_helper(note, request, context):
+
+ if request.method == 'POST':
+ context['note_edit_form'] = NoteForm(request.POST)
+ else:
+ tags_string = ','.join([str(tag) for tag in note.tags.all()])
+ context['note_edit_form'] = NoteForm(initial={'name': note.name,
+ 'tags': tags_string})
+
+ context['note_delete_form'] = NoteDeleteForm(initial={'note': note.id})
+
+ if note.is_pdf():
+ context['pdf_controls'] = True
+
+ if request.user.is_authenticated():
+ try:
+ request.user.get_profile().thanked_notes.get(pk=note.pk)
+ context['already_thanked'] = True
+ except ObjectDoesNotExist:
+ pass
+
+ try:
+ request.user.get_profile().flagged_notes.get(pk=note.pk)
+ context['already_flagged'] = True
+ except ObjectDoesNotExist:
+ pass
+
+
class NoteDetailView(DetailView):
""" Class-based view for the note html page """
model = Note
context_object_name = u"note" # name passed to template
- keyword_form_class = formset_factory(KeywordForm)
-
- def post(self, request, *args, **kwargs):
- formset = self.keyword_form_class(request.POST)
- if formset.is_valid():
- self.keyword_form_valid(formset)
- self.keyword_formset = self.keyword_form_class(initial=self.get_initial_keywords())
- return super(NoteDetailView, self).get(request, *args, **kwargs)
- else:
- self.keyword_formset = formset
- return super(NoteDetailView, self).get(request, *args, **kwargs)
-
- def get(self, request, *args, **kwargs):
- self.keyword_formset = self.keyword_form_class(initial=self.get_initial_keywords())
- return super(NoteDetailView, self).get(request, *args, **kwargs)
+ template_name = 'notes/note_base.html'
def get_context_data(self, **kwargs):
""" Generate custom context for the page rendering a Note
+ if pdf, set the `pdf` flag
"""
- kwargs['keyword_prototype_form'] = KeywordForm
- kwargs['keyword_formset'] = self.keyword_formset
- kwargs['keywords'] = Keyword.objects.filter(note=self.object)
-
- if self.object.is_pdf():
- kwargs['pdf_controls'] = True
+ kwargs['show_note_container'] = True
- if self.request.user.is_authenticated():
- try:
- self.request.user.get_profile().thanked_notes.get(pk=self.object.pk)
- kwargs['already_thanked'] = True
- except ObjectDoesNotExist:
- pass
-
- try:
- self.request.user.get_profile().flagged_notes.get(pk=self.object.pk)
- kwargs['already_flagged'] = True
- except ObjectDoesNotExist:
- pass
+ note_page_context_helper(self.object, self.request, kwargs)
return super(NoteDetailView, self).get_context_data(**kwargs)
- def get_initial_keywords(self):
- existing_keywords = self.get_object().keyword_set.order_by('id')
- initial_data = [{'keyword': keyword.word, 'definition': keyword.definition, 'id': keyword.pk}
- for keyword in existing_keywords]
- return initial_data
-
- def keyword_form_valid(self, formset):
- for form in formset:
- word = form['keyword'].data
- definition = form['definition'].data
- id = form['id'].data
- if word == '':
- continue
- try:
- keyword_object = Keyword.objects.get(id=id)
- except (ValueError, ObjectDoesNotExist):
- keyword_object = Keyword()
-
- keyword_object.note = self.get_object()
- keyword_object.word = word
- keyword_object.definition = definition
- keyword_object.save()
-
class NoteSaveView(FormView, SingleObjectMixin):
""" Save a Note and then view the page,
"""
form_class = NoteForm
model = Note
- template_name = 'notes/note_detail.html'
+ template_name = 'notes/note_base.html'
+
+ def post(self, request, *args, **kwargs):
+ self.object = self.get_object()
+ if self.object.user != request.user:
+ raise ValidationError("Only the owner of a note can edit it.")
+ return super(NoteSaveView, self).post(request, *args, **kwargs)
+
+ def get_success_url(self):
+ return self.object.get_absolute_url()
def get_context_data(self, **kwargs):
context = {
}
return super(NoteSaveView, self).get_context_data(**context)
- def get_success_url(self):
- """ On form submission success, redirect to what url """
- #TODO: redirect to note slug if possible (auto-slugify)
- return u'/{school_slug}/{course_slug}?url=/{school_slug}/{course_slug}/{pk}&name={name}&thankyou'.format(
- school_slug=self.object.course.school.slug,
- course_slug=self.object.course.slug,
- pk=self.object.pk,
- name=self.object.name
- )
-
def form_valid(self, form):
""" Actions to take if the submitted form is valid
namely, saving the new data to the existing note object
"""
- self.object = self.get_object()
if len(form.cleaned_data['name'].strip()) > 0:
self.object.name = form.cleaned_data['name']
- self.object.year = form.cleaned_data['year']
# use *arg expansion to pass tags a list of tags
- self.object.tags.add(*form.cleaned_data['tags'])
+ self.object.tags.set(*form.cleaned_data['tags'])
# User has submitted this form, so set the SHOW flag
self.object.is_hidden = False
self.object.save()
return view(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
- if request.POST['action'] == 'tags-form':
- view = NoteSaveView.as_view()
- else:
- view = NoteDetailView.as_view()
+ view = NoteSaveView.as_view()
return view(request, *args, **kwargs)
+class NoteDeleteView(FormView):
+ form_class = NoteDeleteForm
+
+ def form_valid(self, form):
+ self.note = Note.objects.get(id=form.cleaned_data['note'])
+ self.note.is_hidden = True
+ self.note.save()
+
+ messages.success(self.request, 'The note "{0}" was deleted successfully.'.format(self.note.name))
+
+ return super(FormView, self).form_valid(form)
+
+ def get_success_url(self):
+ return self.note.course.get_absolute_url()
+
+
+class NoteKeywordsView(FormView, SingleObjectMixin):
+ """ Class-based view for the note html page """
+ model = Note
+ context_object_name = u"note" # name passed to template
+ form_class = formset_factory(KeywordForm)
+ template_name = 'notes/note_base.html'
+
+ def get_object(self, queryset=None):
+ return Note.objects.get(slug=self.kwargs['slug'])
+
+ def post(self, request, *args, **kwargs):
+ self.object = self.get_object()
+ if not self.request.user.is_authenticated():
+ raise ValidationError("Only authenticated users may set keywords.")
+
+ formset = self.form_class(request.POST)
+ if formset.is_valid():
+ self.keyword_form_valid(formset)
+ self.keyword_formset = self.form_class(initial=self.get_initial_keywords())
+ return super(NoteKeywordsView, self).get(request, *args, **kwargs)
+ else:
+ self.keyword_formset = formset
+ return super(NoteKeywordsView, self).get(request, *args, **kwargs)
+
+ def get(self, request, *args, **kwargs):
+ self.object = self.get_object()
+ self.keyword_formset = self.form_class(initial=self.get_initial_keywords())
+ return super(NoteKeywordsView, self).get(request, *args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ kwargs['keyword_prototype_form'] = KeywordForm
+ kwargs['keyword_formset'] = self.keyword_formset
+ kwargs['keywords'] = Keyword.objects.filter(note=self.get_object())
+ kwargs['show_keywords'] = True
+
+ note_page_context_helper(self.get_object(), self.request, kwargs)
+
+ return super(NoteKeywordsView, self).get_context_data(**kwargs)
+
+ def get_initial_keywords(self):
+ existing_keywords = self.get_object().keyword_set.order_by('id')
+ initial_data = [{'keyword': keyword.word, 'definition': keyword.definition, 'id': keyword.pk}
+ for keyword in existing_keywords]
+ return initial_data
+
+ def keyword_form_valid(self, formset):
+ for form in formset:
+ word = form['keyword'].data
+ definition = form['definition'].data
+ id = form['id'].data
+ # If the user has deleted an existing keyword
+ if not word and not definition and id:
+ try:
+ keyword_object = Keyword.objects.get(id=id)
+ keyword_object.delete()
+ except (ValueError, ObjectDoesNotExist):
+ pass
+
+ # otherwise get or create a keyword
+ elif word or definition:
+ try:
+ keyword_object = Keyword.objects.get(id=id)
+ except (ValueError, ObjectDoesNotExist):
+ keyword_object = Keyword()
+ NoteKarmaEvent.create_event(self.request.user, self.get_object(), NoteKarmaEvent.CREATED_KEYWORD)
+
+ keyword_object.note = self.get_object()
+ keyword_object.word = word
+ keyword_object.definition = definition
+ keyword_object.unreviewed = False
+ keyword_object.save()
+
+
+class NoteQuizView(TemplateView):
+ template_name = 'notes/note_base.html'
+
+ def get_context_data(self, **kwargs):
+ note = Note.objects.get(slug=self.kwargs['slug'])
+
+ note_page_context_helper(note, self.request, kwargs)
+
+ kwargs['note'] = note
+ kwargs['questions'] = quiz_from_keywords(note)
+ kwargs['show_quiz'] = True
+
+ return super(NoteQuizView, self).get_context_data(**kwargs)
+
+
class NoteSearchView(ListView):
template_name = 'notes/search_results.html'
if note.user != request_user and note.user:
NoteKarmaEvent.create_event(note.user, note, NoteKarmaEvent.THANKS)
+ # If note thanks exceeds a threshold, create a Mechanical
+ # Turk task to get some keywords for it
+ if note.thanks == KEYWORD_MTURK_THRESHOLD:
+ submit_extract_keywords_hit.delay(note)
+
def thank_note(request, pk):
"""Record that somebody has thanked a note."""
"""Record that somebody has downloaded a note"""
if request_user.is_authenticated() and request_user != note.user:
NoteKarmaEvent.create_event(request_user, note, NoteKarmaEvent.DOWNLOADED_NOTE)
- if request_user.is_authenticated() and note.user:
+ if request_user.is_authenticated() and note.user and note.user != request_user:
NoteKarmaEvent.create_event(note.user, note, NoteKarmaEvent.HAD_NOTE_DOWNLOADED)