3 # Copyright (C) 2012 FinalsClub Foundation
9 from django.core import serializers
10 from django.core.exceptions import ObjectDoesNotExist
11 from karmaworld.apps.courses.models import Course
12 from karmaworld.apps.notes.search import SearchIndex
13 from karmaworld.apps.users.models import NoteKarmaEvent
14 from karmaworld.utils.ajax_utils import *
18 from django.conf import settings
19 from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound
20 from django.views.generic import DetailView, ListView
21 from django.views.generic import FormView
22 from django.views.generic import View
23 from django.views.generic.detail import SingleObjectMixin
25 from karmaworld.apps.notes.models import Note
26 from karmaworld.apps.notes.forms import NoteForm
29 logger = logging.getLogger(__name__)
31 THANKS_FIELD = 'thanks'
32 USER_PROFILE_THANKS_FIELD = 'thanked_notes'
34 USER_PROFILE_FLAGS_FIELD = 'flagged_notes'
37 class NoteDetailView(DetailView):
38 """ Class-based view for the note html page """
40 context_object_name = u"note" # name passed to template
42 def get_context_data(self, **kwargs):
43 """ Generate custom context for the page rendering a Note
44 + if pdf, set the `pdf` flag
46 if self.object.is_pdf():
47 kwargs['pdf_controls'] = True
49 if self.request.user.is_authenticated():
51 self.request.user.get_profile().thanked_notes.get(pk=self.object.pk)
52 kwargs['already_thanked'] = True
53 except ObjectDoesNotExist:
57 self.request.user.get_profile().flagged_notes.get(pk=self.object.pk)
58 kwargs['already_flagged'] = True
59 except ObjectDoesNotExist:
62 return super(NoteDetailView, self).get_context_data(**kwargs)
65 class NoteSaveView(FormView, SingleObjectMixin):
66 """ Save a Note and then view the page,
67 behaves the same as NoteDetailView, except for saving the
72 template_name = 'notes/note_detail.html'
74 def get_context_data(self, **kwargs):
76 'object': self.get_object(),
78 print "get context for NoteSaveView"
79 return super(NoteSaveView, self).get_context_data(**context)
81 def get_success_url(self):
82 """ On form submission success, redirect to what url """
83 #TODO: redirect to note slug if possible (auto-slugify)
84 return u'/{school_slug}/{course_slug}?url=/{school_slug}/{course_slug}/{pk}&name={name}&thankyou'.format(
85 school_slug=self.object.course.school.slug,
86 course_slug=self.object.course.slug,
91 def form_valid(self, form):
92 """ Actions to take if the submitted form is valid
93 namely, saving the new data to the existing note object
95 self.object = self.get_object()
96 if len(form.cleaned_data['name'].strip()) > 0:
97 self.object.name = form.cleaned_data['name']
98 self.object.year = form.cleaned_data['year']
99 # use *arg expansion to pass tags a list of tags
100 self.object.tags.add(*form.cleaned_data['tags'])
101 # User has submitted this form, so set the SHOW flag
102 self.object.is_hidden = False
104 return super(NoteSaveView, self).form_valid(form)
106 def form_invalid(self, form):
107 """ Do stuff when the form is invalid !!! TODO """
108 # TODO: implement def form_invalid for returning a form with input and error
109 print "running form_invalid"
114 class NoteView(View):
115 """ Notes superclass that wraps http methods """
117 def get(self, request, *args, **kwargs):
118 view = NoteDetailView.as_view()
119 return view(request, *args, **kwargs)
121 def post(self, request, *args, **kwargs):
122 view = NoteSaveView.as_view()
123 return view(request, *args, **kwargs)
126 class RawNoteDetailView(DetailView):
127 """ Class-based view for the raw note html for iframes """
128 template_name = u'notes/note_raw.html'
129 context_object_name = u"note"
133 class NoteSearchView(ListView):
134 template_name = 'notes/search_results.html'
136 def get_queryset(self):
137 if not 'query' in self.request.GET:
138 return Note.objects.none()
140 if 'page' in self.request.GET:
141 page = int(self.request.GET['page'])
146 index = SearchIndex()
148 if 'course_id' in self.request.GET:
149 raw_results = index.search(self.request.GET['query'],
150 self.request.GET['course_id'],
153 raw_results = index.search(self.request.GET['query'],
157 logger.error("Error with IndexDen:\n" + traceback.format_exc())
159 return Note.objects.none()
163 instances = Note.objects.in_bulk(raw_results.ordered_ids)
165 for id in raw_results.ordered_ids:
167 results.append((instances[id], raw_results.snippet_dict[id]))
168 self.has_more = raw_results.has_more
172 def get_context_data(self, **kwargs):
173 if 'query' in self.request.GET:
174 kwargs['query'] = self.request.GET['query']
176 if 'course_id' in self.request.GET:
177 kwargs['course'] = Course.objects.get(id=self.request.GET['course_id'])
180 kwargs['error'] = True
181 return super(NoteSearchView, self).get_context_data(**kwargs)
183 # If query returned more search results than could
184 # fit on one page, show "Next" button
186 kwargs['has_next'] = True
187 if 'page' in self.request.GET:
188 kwargs['next_page'] = int(self.request.GET['page']) + 1
190 kwargs['next_page'] = 1
192 # If the user is looking at a search result page
193 # that isn't the first one, show "Prev" button
194 if 'page' in self.request.GET and \
195 int(self.request.GET['page']) > 0:
196 kwargs['has_prev'] = True
197 kwargs['prev_page'] = int(self.request.GET['page']) - 1
199 return super(NoteSearchView, self).get_context_data(**kwargs)
202 def process_note_thank_events(request_user, note):
203 # Give points to the person who uploaded this note
204 if note.user != request_user and note.user:
205 NoteKarmaEvent.create_event(note.user, note, NoteKarmaEvent.THANKS)
208 def thank_note(request, pk):
209 """Record that somebody has thanked a note."""
210 return ajax_increment(Note, request, pk, THANKS_FIELD, USER_PROFILE_THANKS_FIELD, process_note_thank_events)
213 def process_note_flag_events(request_user, note):
214 # Take a point away from person flagging this note
215 if request_user.is_authenticated():
216 NoteKarmaEvent.create_event(request_user, note, NoteKarmaEvent.GIVE_FLAG)
217 # If this is the 6th time this note has been flagged,
218 # punish the uploader
219 if note.flags == 6 and note.user:
220 NoteKarmaEvent.create_event(note.user, note, NoteKarmaEvent.GET_FLAGGED)
223 def flag_note(request, pk):
224 """Record that somebody has flagged a note."""
225 return ajax_increment(Note, request, pk, FLAG_FIELD, USER_PROFILE_FLAGS_FIELD, process_note_flag_events)
228 def process_downloaded_note(request_user, note):
229 """Record that somebody has downloaded a note"""
230 if request_user.is_authenticated() and request_user != note.user:
231 NoteKarmaEvent.create_event(request_user, note, NoteKarmaEvent.DOWNLOADED_NOTE)
232 if request_user.is_authenticated() and note.user:
233 NoteKarmaEvent.create_event(note.user, note, NoteKarmaEvent.HAD_NOTE_DOWNLOADED)
236 def downloaded_note(request, pk):
237 """Record that somebody has flagged a note."""
238 return ajax_pk_base(Note, request, pk, process_downloaded_note)
241 def edit_note_tags(request, pk):
243 Saves the posted string of tags
245 if request.method == "POST" and request.is_ajax() and request.user.is_authenticated() and request.user.get_profile().can_edit_items():
246 note = Note.objects.get(pk=pk)
247 note.tags.set(request.body)
249 note_json = serializers.serialize('json', [note,])
250 resp = json.loads(note_json)[0]
251 resp['fields']['tags'] = list(note.tags.names())
253 return HttpResponse(json.dumps(resp), mimetype="application/json")
255 return HttpResponseBadRequest(json.dumps({'status': 'fail', 'message': 'Invalid request'}),
256 mimetype="application/json")