From: Charles Connell Date: Mon, 28 Apr 2014 21:14:34 +0000 (-0400) Subject: Edit and delete notes X-Git-Tag: release-20150131~111 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=e55707c2bcce55302313b79569d49f682d086b7e;p=oweals%2Fkarmaworld.git Edit and delete notes --- diff --git a/karmaworld/apps/notes/forms.py b/karmaworld/apps/notes/forms.py index 0759ffb..df59404 100644 --- a/karmaworld/apps/notes/forms.py +++ b/karmaworld/apps/notes/forms.py @@ -1,23 +1,26 @@ #!/usr/bin/env python # -*- coding:utf8 -*- # Copyright (C) 2012 FinalsClub Foundation - -from django.forms import ModelForm +from django.forms import ModelForm, IntegerField, HiddenInput, Form from django.forms import TextInput - -from django_filepicker.forms import FPFileField from django_filepicker.widgets import FPFileWidget from karmaworld.apps.notes.models import Note + class NoteForm(ModelForm): class Meta: model = Note - fields = ('name', 'tags', 'year',) + fields = ('name', 'tags',) widgets = { 'name': TextInput() } + +class NoteDeleteForm(Form): + note = IntegerField(widget=HiddenInput()) + + class FileUploadForm(ModelForm): auto_id = False class Meta: diff --git a/karmaworld/apps/notes/views.py b/karmaworld/apps/notes/views.py index 2fd1bc2..d1db236 100644 --- a/karmaworld/apps/notes/views.py +++ b/karmaworld/apps/notes/views.py @@ -4,8 +4,10 @@ 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.models import Course from karmaworld.apps.notes.search import SearchIndex @@ -21,7 +23,7 @@ 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.forms import NoteForm, NoteDeleteForm logger = logging.getLogger(__name__) @@ -33,6 +35,16 @@ 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 @@ -76,32 +88,29 @@ class NoteSaveView(FormView, SingleObjectMixin): model = Note template_name = 'notes/note_detail.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 = { 'object': self.get_object(), } 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() @@ -127,6 +136,22 @@ class NoteView(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 @@ -256,6 +281,34 @@ class NoteSearchView(ListView): return super(NoteSearchView, self).get_context_data(**kwargs) +def handle_edit_note(request): + course = Course.objects.get(pk=pk) + original_name = course.name + course_form = CourseForm(request.POST or None, instance=course) + + if course_form.is_valid(): + course_form.save() + + course_json = serializers.serialize('json', [course,]) + resp = json.loads(course_json)[0] + + if (course.name != original_name): + course.set_slug() + resp['fields']['new_url'] = course.get_absolute_url() + + return HttpResponse(json.dumps(resp), mimetype="application/json") + else: + return HttpResponseBadRequest(json.dumps({'status': 'fail', 'message': 'Validation error', + 'errors': course_form.errors}), + mimetype="application/json") + +def edit_note(request, pk): + """ + Saves the edited note metadata + """ + ajax_base(request, edit_note, ['POST']) + + def process_note_thank_events(request_user, note): # Give points to the person who uploaded this note if note.user != request_user and note.user: diff --git a/karmaworld/assets/css/global.css b/karmaworld/assets/css/global.css index 601e76a..c0cffad 100644 --- a/karmaworld/assets/css/global.css +++ b/karmaworld/assets/css/global.css @@ -113,6 +113,10 @@ button.inline-button { display: inline; } +button.scary { + background-color: #F12A2A; +} + .joyride-content-wrapper .button { background-color: #008CBA; } diff --git a/karmaworld/assets/js/note-detail.js b/karmaworld/assets/js/note-detail.js index e5d316a..81e3d79 100644 --- a/karmaworld/assets/js/note-detail.js +++ b/karmaworld/assets/js/note-detail.js @@ -208,6 +208,12 @@ $(function() { }; }); + $('#delete-note-button').click(function (event) { + if (!confirm("Are you sure you want to delete this note?")) { + event.preventDefault(); + } + }); + // Embed the converted markdown if it is on the page, else default to the iframe if ($('#note-markdown').length > 0) { var note_markdown = $('#note-markdown'); diff --git a/karmaworld/templates/notes/note_detail.html b/karmaworld/templates/notes/note_detail.html index e2e11b7..caec759 100644 --- a/karmaworld/templates/notes/note_detail.html +++ b/karmaworld/templates/notes/note_detail.html @@ -26,7 +26,7 @@ var annotator_js_url = "{{ STATIC_URL }}js/annotator-full.min.js"; var annotator_css_url = "{{ STATIC_URL }}css/annotator.min.css"; var setup_ajax_url = "{{ STATIC_URL }}js/setup-ajax.js"; - var empty_js = "{{ STATIC_URL }}js/empty.js"; + var note_edit_url = "{% url 'edit_note' note.id %}"; {% compress js %} @@ -129,11 +129,19 @@ Download Note {% endif %} - {% if user.get_profile.can_edit_items %} + {% if user.get_profile.can_edit_items and note.user != user %} {% endif %} + + {% if note.user == request.user %} +    + {% endif %} + + {% if note.license %} + {{ note.license.html|safe }} {% if note.upstream_link %}{{ note.upstream_link|slice:":80" }}{% endif %} + {% endif %} @@ -144,7 +152,9 @@ Tags: {% for tag in note.tags.all %} - {{ tag.name }} + + {{ tag.name }}{% if not forloop.last %}, {% endif %} + {% endfor %} @@ -154,20 +164,52 @@ ×
-

Edit this note's tags: -

+

Edit this note's tags

+
- {% if note.license %} +
+ ×
-
- {{ note.license.html|safe }} {% if note.upstream_link %}{{ note.upstream_link|slice:":80" }}{% endif %} -
+
+

Edit Your Note

+
+
+
+ {% csrf_token %} + {{ note_delete_form }} + +
+
- {% endif %} +
+
+ {% csrf_token %} +
+ {% with note_edit_form.name as field %} + {{ field.errors|safe }} + + {{ field }} +

{{ field.help_text }}

+ {% endwith %} +
+
+ {% with note_edit_form.tags as field %} + {{ field.errors|safe }} + + {{ field }} +

{{ field.help_text }}

+ {% endwith %} +
+
+ +
+
+
+
diff --git a/karmaworld/urls.py b/karmaworld/urls.py index b1d0f63..eccdde5 100644 --- a/karmaworld/urls.py +++ b/karmaworld/urls.py @@ -15,7 +15,7 @@ from karmaworld.apps.courses.views import CourseListView from karmaworld.apps.courses.views import school_course_list from karmaworld.apps.courses.views import school_course_instructor_list from karmaworld.apps.notes.views import NoteView, thank_note, NoteSearchView, flag_note, downloaded_note, edit_note_tags, \ - NoteKeywordsView + NoteKeywordsView, edit_note, NoteDeleteView from karmaworld.apps.moderation import moderator from karmaworld.apps.document_upload.views import save_fp_upload from karmaworld.apps.quizzes.views import QuizView, KeywordEditView, quiz_answer, get_keywords_annotator, \ @@ -98,6 +98,7 @@ urlpatterns = patterns('', url(r'^ajax/course/flag/(?P[\d]+)/$', flag_course, name='flag_course'), # Ajax endpoint to edit a course url(r'^ajax/course/edit/(?P[\d]+)/$', edit_course, name='edit_course'), + url(r'^ajax/note/edit/(?P[\d]+)/$', edit_note, name='edit_note'), # Check if a quiz answer is correct url(r'^ajax/quiz/check/$', quiz_answer, name='quiz_answer'), @@ -119,6 +120,8 @@ urlpatterns = patterns('', url(r'^note/' + SLUG.format('school_') + '/' + SLUG.format('course_') +'/'+ SLUG.format('') +'/keywords/$', NoteKeywordsView.as_view(), name='note_keywords'), + url(r'note/delete/$', NoteDeleteView.as_view(), name='note_delete'), + # Quizzes url(r'^quiz/(?P[\d]+)/$', QuizView.as_view(), name='quiz'),