Commit 3fe44fc09c899c27c80f10f7c07a9003f106ca3b

Authored by Matheus Lins
1 parent a4d0a0ff

conflix

amadeus/settings.py
@@ -46,6 +46,7 @@ INSTALLED_APPS = [ @@ -46,6 +46,7 @@ INSTALLED_APPS = [
46 'rest_framework', 46 'rest_framework',
47 'django_bootstrap_breadcrumbs', 47 'django_bootstrap_breadcrumbs',
48 's3direct', 48 's3direct',
  49 + 'django_summernote',
49 50
50 'users', 51 'users',
51 'core', 52 'core',
@@ -225,7 +226,59 @@ S3DIRECT_DESTINATIONS = { @@ -225,7 +226,59 @@ S3DIRECT_DESTINATIONS = {
225 # FILE UPLOAD 226 # FILE UPLOAD
226 MAX_UPLOAD_SIZE = 10485760 227 MAX_UPLOAD_SIZE = 10485760
227 228
  229 +SUMMERNOTE_CONFIG = {
  230 + # Using SummernoteWidget - iframe mode
  231 + 'iframe': True, # or set False to use SummernoteInplaceWidget - no iframe mode
  232 +
  233 + # Using Summernote Air-mode
  234 + 'airMode': False,
  235 +
  236 + # Use native HTML tags (`<b>`, `<i>`, ...) instead of style attributes
  237 + # (Firefox, Chrome only)
  238 + 'styleWithTags': True,
  239 +
  240 + # Set text direction : 'left to right' is default.
  241 + 'direction': 'ltr',
  242 +
  243 + # Change editor size
  244 + 'width': '100%',
  245 + 'height': '480',
  246 +
  247 + # Use proper language setting automatically (default)
  248 + 'lang': None,
  249 +
  250 + # Or, set editor language/locale forcely
  251 + 'lang_matches': {
  252 + 'pt': 'pt-BR',
  253 + },
  254 +
  255 + # Customize toolbar buttons
  256 + 'toolbar': [
  257 + ['style', ['style']],
  258 + ['font', ['bold', 'italic', 'underline', 'superscript', 'subscript',
  259 + 'strikethrough', 'clear']],
  260 + ['fontname', ['fontname']],
  261 + ['fontsize', ['fontsize']],
  262 + ['color', ['color']],
  263 + ['para', ['ul', 'ol', 'paragraph']],
  264 + ['height', ['height']],
  265 + ['table', ['table']],
  266 + ['insert', ['link', 'picture', 'video', 'hr']],
  267 + ['view', ['fullscreen', 'codeview']],
  268 + ['help', ['help']],
  269 + ],
  270 +
  271 + # Need authentication while uploading attachments.
  272 + 'attachment_require_authentication': True,
  273 +
  274 + # Set `upload_to` function for attachments.
  275 + #'attachment_upload_to': my_custom_upload_to_func(),
  276 +
  277 +
  278 +
  279 +}
  280 +
228 try: 281 try:
229 from .local_settings import * 282 from .local_settings import *
230 except ImportError: 283 except ImportError:
231 - pass 284 - pass
  285 + pass
232 \ No newline at end of file 286 \ No newline at end of file
amadeus/urls.py
@@ -28,6 +28,7 @@ urlpatterns = [ @@ -28,6 +28,7 @@ urlpatterns = [
28 28
29 #S3Direct 29 #S3Direct
30 url(r'^s3direct/', include('s3direct.urls')), 30 url(r'^s3direct/', include('s3direct.urls')),
  31 + url(r'^summernote/', include('django_summernote.urls')),
31 ] 32 ]
32 33
33 urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT) 34 urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
core/mixins.py
@@ -34,9 +34,6 @@ class LogMixin(object): @@ -34,9 +34,6 @@ class LogMixin(object):
34 else: 34 else:
35 action_resource = action_resource[0] 35 action_resource = action_resource[0]
36 36
37 - print(context)  
38 - print(json.dumps(context))  
39 -  
40 log = Log() 37 log = Log()
41 log.user = actor 38 log.user = actor
42 log.context = json.dumps(context) 39 log.context = json.dumps(context)
courses/forms.py
@@ -2,7 +2,7 @@ from django import forms @@ -2,7 +2,7 @@ from django import forms
2 from django.utils.translation import ugettext_lazy as _ 2 from django.utils.translation import ugettext_lazy as _
3 from .models import CourseCategory, Course, Subject, Topic, ActivityFile, Activity, FileMaterial, LinkMaterial 3 from .models import CourseCategory, Course, Subject, Topic, ActivityFile, Activity, FileMaterial, LinkMaterial
4 from s3direct.widgets import S3DirectWidget 4 from s3direct.widgets import S3DirectWidget
5 - 5 +from django_summernote.widgets import SummernoteWidget
6 6
7 class CategoryCourseForm(forms.ModelForm): 7 class CategoryCourseForm(forms.ModelForm):
8 8
@@ -79,8 +79,8 @@ class CourseForm(forms.ModelForm): @@ -79,8 +79,8 @@ class CourseForm(forms.ModelForm):
79 79
80 widgets = { 80 widgets = {
81 'categoy': forms.Select(), 81 'categoy': forms.Select(),
82 - 'objectivies': forms.Textarea(attrs={'cols': 80, 'rows': 5}),  
83 - 'content': forms.Textarea(attrs={'cols': 80, 'rows': 5}), 82 + 'objectivies': SummernoteWidget(attrs={'cols': 80, 'rows': 5}),
  83 + 'content': SummernoteWidget(attrs={'cols': 80, 'rows': 5}),
84 } 84 }
85 85
86 class UpdateCourseForm(CourseForm): 86 class UpdateCourseForm(CourseForm):
@@ -120,8 +120,8 @@ class UpdateCourseForm(CourseForm): @@ -120,8 +120,8 @@ class UpdateCourseForm(CourseForm):
120 } 120 }
121 widgets = { 121 widgets = {
122 'categoy': forms.Select(), 122 'categoy': forms.Select(),
123 - 'objectivies': forms.Textarea(attrs={'cols': 80, 'rows': 5}),  
124 - 'content': forms.Textarea(attrs={'cols': 80, 'rows': 5}), 123 + 'objectivies': SummernoteWidget(attrs={'cols': 80, 'rows': 5}),
  124 + 'content': SummernoteWidget(attrs={'cols': 80, 'rows': 5}),
125 } 125 }
126 126
127 class SubjectForm(forms.ModelForm): 127 class SubjectForm(forms.ModelForm):
@@ -143,6 +143,9 @@ class SubjectForm(forms.ModelForm): @@ -143,6 +143,9 @@ class SubjectForm(forms.ModelForm):
143 'end_date': _('End date of the subject'), 143 'end_date': _('End date of the subject'),
144 'visible': _('Is the subject visible?'), 144 'visible': _('Is the subject visible?'),
145 } 145 }
  146 + widgets = {
  147 + 'description':SummernoteWidget(),
  148 + }
146 149
147 class TopicForm(forms.ModelForm): 150 class TopicForm(forms.ModelForm):
148 151
@@ -157,6 +160,9 @@ class TopicForm(forms.ModelForm): @@ -157,6 +160,9 @@ class TopicForm(forms.ModelForm):
157 'name': _("Topic's name"), 160 'name': _("Topic's name"),
158 'description': _("Topic's description"), 161 'description': _("Topic's description"),
159 } 162 }
  163 + widgets = {
  164 + 'description':SummernoteWidget(),
  165 + }
160 166
161 class ActivityFileForm(forms.ModelForm): 167 class ActivityFileForm(forms.ModelForm):
162 name = forms.CharField( 168 name = forms.CharField(
courses/static/js/topic_editation_presentation.js
@@ -5,7 +5,8 @@ function show_editation(id_topic){ @@ -5,7 +5,8 @@ function show_editation(id_topic){
5 $(".presentation_"+ id_topic).css('display','none'); 5 $(".presentation_"+ id_topic).css('display','none');
6 $(".editation_"+ id_topic).css('display','block'); 6 $(".editation_"+ id_topic).css('display','block');
7 }; 7 };
8 - function show_presentation(id_topic){ 8 +
  9 +function show_presentation(id_topic){
9 $(".editation_"+ id_topic).css('display','none'); 10 $(".editation_"+ id_topic).css('display','none');
10 $(".presentation_"+ id_topic).css('display','block'); 11 $(".presentation_"+ id_topic).css('display','block');
11 }; 12 };
courses/templates/course/course_card.html
@@ -38,7 +38,7 @@ @@ -38,7 +38,7 @@
38 <p> 38 <p>
39 <b>{% trans 'Description' %}:</b> 39 <b>{% trans 'Description' %}:</b>
40 <i> 40 <i>
41 - {{course.content}} 41 + {{course.content | safe }}
42 </i> 42 </i>
43 </p> 43 </p>
44 </div> 44 </div>
courses/templates/course/view.html
@@ -98,7 +98,7 @@ @@ -98,7 +98,7 @@
98 <p> 98 <p>
99 <b>{% trans 'Description' %}:</b> 99 <b>{% trans 'Description' %}:</b>
100 <i> 100 <i>
101 - {{ course.objectivies }} 101 + {{ course.objectivies |safe }}
102 </i> 102 </i>
103 </p> 103 </p>
104 104
@@ -174,7 +174,7 @@ @@ -174,7 +174,7 @@
174 <p> 174 <p>
175 <b>{% trans "Description" %}: </b> 175 <b>{% trans "Description" %}: </b>
176 <i> 176 <i>
177 - {{subject.description}} 177 + {{subject.description | safe}}
178 </i> 178 </i>
179 </p> 179 </p>
180 <div class="row"> 180 <div class="row">
courses/templates/subject/form_view_student.html
@@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
27 <div class="presentation"> 27 <div class="presentation">
28 <p> 28 <p>
29 <i> 29 <i>
30 - {{topic.description|linebreaks}} 30 + {{topic.description|safe}}
31 </i> 31 </i>
32 </p> 32 </p>
33 33
courses/templates/subject/form_view_teacher.html
@@ -39,7 +39,7 @@ @@ -39,7 +39,7 @@
39 <div class="presentation_{{topic.slug}}"> 39 <div class="presentation_{{topic.slug}}">
40 <p> 40 <p>
41 <i> 41 <i>
42 - {{topic.description|linebreaks}} 42 + {{topic.description|safe}}
43 </i> 43 </i>
44 </p> 44 </p>
45 </div> 45 </div>
courses/templates/subject/index.html
@@ -75,7 +75,7 @@ @@ -75,7 +75,7 @@
75 {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}</p> 75 {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}</p>
76 <p> 76 <p>
77 <b>{% trans "Description" %}:</b> 77 <b>{% trans "Description" %}:</b>
78 - {{subject.description|linebreaks}} 78 + {{subject.description|safe}}
79 </p> 79 </p>
80 <div class="row"> 80 <div class="row">
81 <div class="col-xs-6 col-md-6"> 81 <div class="col-xs-6 col-md-6">
courses/templates/subject_category/index.html
@@ -58,7 +58,7 @@ @@ -58,7 +58,7 @@
58 </div> 58 </div>
59 <div class="panel-body"> 59 <div class="panel-body">
60 <p> 60 <p>
61 - {{subject.description|linebreaks}} 61 + {{subject.description| safe }}
62 </p> 62 </p>
63 </div> 63 </div>
64 </div> 64 </div>
courses/templates/topic/index.html
@@ -77,7 +77,7 @@ @@ -77,7 +77,7 @@
77 </div> 77 </div>
78 <div class="panel-body"> 78 <div class="panel-body">
79 <p> 79 <p>
80 - {{topic.description|linebreaks}} 80 + {{topic.description|safe}}
81 </p> 81 </p>
82 </div> 82 </div>
83 </div> 83 </div>
courses/views.py
@@ -284,21 +284,12 @@ class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.Delet @@ -284,21 +284,12 @@ class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.Delet
284 redirect_field_name = 'next' 284 redirect_field_name = 'next'
285 model = Course 285 model = Course
286 template_name = 'course/delete.html' 286 template_name = 'course/delete.html'
287 - success_url = reverse_lazy('course:manage')  
288 287
289 def dispatch(self, *args, **kwargs): 288 def dispatch(self, *args, **kwargs):
290 course = get_object_or_404(Course, slug = self.kwargs.get('slug')) 289 course = get_object_or_404(Course, slug = self.kwargs.get('slug'))
291 if(not has_object_permission('delete_course', self.request.user, course)): 290 if(not has_object_permission('delete_course', self.request.user, course)):
292 return self.handle_no_permission() 291 return self.handle_no_permission()
293 292
294 - self.log_context['course_id'] = course.id  
295 - self.log_context['course_name'] = course.name  
296 - self.log_context['course_slug'] = course.slug  
297 - self.log_context['course_category_id'] = course.category.id  
298 - self.log_context['course_category_name'] = course.category.name  
299 -  
300 - super(DeleteCourseView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)  
301 -  
302 return super(DeleteCourseView, self).dispatch(*args, **kwargs) 293 return super(DeleteCourseView, self).dispatch(*args, **kwargs)
303 294
304 def get_context_data(self, **kwargs): 295 def get_context_data(self, **kwargs):
@@ -314,6 +305,17 @@ class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.Delet @@ -314,6 +305,17 @@ class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.Delet
314 305
315 return context 306 return context
316 307
  308 + def get_success_url(self):
  309 + self.log_context['course_id'] = self.object.id
  310 + self.log_context['course_name'] = self.object.name
  311 + self.log_context['course_slug'] = self.object.slug
  312 + self.log_context['course_category_id'] = self.object.category.id
  313 + self.log_context['course_category_name'] = self.object.category.name
  314 +
  315 + super(DeleteCourseView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  316 +
  317 + return reverse_lazy('course:manage')
  318 +
317 319
318 class CourseView(LogMixin, NotificationMixin, generic.DetailView): 320 class CourseView(LogMixin, NotificationMixin, generic.DetailView):
319 log_component = "courses" 321 log_component = "courses"
@@ -586,7 +588,11 @@ class UploadMaterialView(LoginRequiredMixin, generic.edit.CreateView): @@ -586,7 +588,11 @@ class UploadMaterialView(LoginRequiredMixin, generic.edit.CreateView):
586 588
587 return self.success_url 589 return self.success_url
588 590
589 -class TopicsView(LoginRequiredMixin, generic.ListView): 591 +class TopicsView(LoginRequiredMixin, LogMixin, generic.ListView):
  592 + log_component = "course"
  593 + log_resource = "topic"
  594 + log_action = "viewed"
  595 + log_context = {}
590 596
591 login_url = reverse_lazy("core:home") 597 login_url = reverse_lazy("core:home")
592 redirect_field_name = 'next' 598 redirect_field_name = 'next'
@@ -600,6 +606,20 @@ class TopicsView(LoginRequiredMixin, generic.ListView): @@ -600,6 +606,20 @@ class TopicsView(LoginRequiredMixin, generic.ListView):
600 if(not has_object_permission('view_topic', self.request.user, topic)): 606 if(not has_object_permission('view_topic', self.request.user, topic)):
601 return self.handle_no_permission() 607 return self.handle_no_permission()
602 608
  609 + self.log_context['topic_id'] = topic.id
  610 + self.log_context['topic_name'] = topic.name
  611 + self.log_context['topic_slug'] = topic.slug
  612 + self.log_context['subject_id'] = topic.subject.id
  613 + self.log_context['subject_name'] = topic.subject.name
  614 + self.log_context['subject_slug'] = topic.subject.slug
  615 + self.log_context['course_id'] = topic.subject.course.id
  616 + self.log_context['course_name'] = topic.subject.course.name
  617 + self.log_context['course_slug'] = topic.subject.course.slug
  618 + self.log_context['course_category_id'] = topic.subject.course.category.id
  619 + self.log_context['course_category_name'] = topic.subject.course.category.name
  620 +
  621 + super(TopicsView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  622 +
603 return super(TopicsView, self).dispatch(*args, **kwargs) 623 return super(TopicsView, self).dispatch(*args, **kwargs)
604 624
605 def get_queryset(self): 625 def get_queryset(self):
@@ -626,7 +646,11 @@ class TopicsView(LoginRequiredMixin, generic.ListView): @@ -626,7 +646,11 @@ class TopicsView(LoginRequiredMixin, generic.ListView):
626 return context 646 return context
627 647
628 648
629 -class CreateTopicView(LoginRequiredMixin, HasRoleMixin, NotificationMixin, generic.edit.CreateView): 649 +class CreateTopicView(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin, generic.edit.CreateView):
  650 + log_component = "course"
  651 + log_resource = "topic"
  652 + log_action = "create"
  653 + log_context = {}
630 654
631 allowed_roles = ['professor', 'system_admin'] 655 allowed_roles = ['professor', 'system_admin']
632 login_url = reverse_lazy("core:home") 656 login_url = reverse_lazy("core:home")
@@ -656,10 +680,28 @@ class CreateTopicView(LoginRequiredMixin, HasRoleMixin, NotificationMixin, gener @@ -656,10 +680,28 @@ class CreateTopicView(LoginRequiredMixin, HasRoleMixin, NotificationMixin, gener
656 super(CreateTopicView, self).createNotification("Topic "+ self.object.name + " was created", 680 super(CreateTopicView, self).createNotification("Topic "+ self.object.name + " was created",
657 resource_name=self.object.name, resource_link= reverse('course:view_topic',args=[self.object.slug]), 681 resource_name=self.object.name, resource_link= reverse('course:view_topic',args=[self.object.slug]),
658 actor=self.request.user, users = self.object.subject.course.students.all() ) 682 actor=self.request.user, users = self.object.subject.course.students.all() )
  683 +
  684 + self.log_context['topic_id'] = self.object.id
  685 + self.log_context['topic_name'] = self.object.name
  686 + self.log_context['topic_slug'] = self.object.slug
  687 + self.log_context['subject_id'] = self.object.subject.id
  688 + self.log_context['subject_name'] = self.object.subject.name
  689 + self.log_context['subject_slug'] = self.object.subject.slug
  690 + self.log_context['course_id'] = self.object.subject.course.id
  691 + self.log_context['course_name'] = self.object.subject.course.name
  692 + self.log_context['course_slug'] = self.object.subject.course.slug
  693 + self.log_context['course_category_id'] = self.object.subject.course.category.id
  694 + self.log_context['course_category_name'] = self.object.subject.course.category.name
  695 +
  696 + super(CreateTopicView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
659 697
660 return super(CreateTopicView, self).form_valid(form) 698 return super(CreateTopicView, self).form_valid(form)
661 699
662 -class UpdateTopicView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): 700 +class UpdateTopicView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.UpdateView):
  701 + log_component = "course"
  702 + log_resource = "topic"
  703 + log_action = "create"
  704 + log_context = {}
663 705
664 allowed_roles = ['professor','system_admin'] 706 allowed_roles = ['professor','system_admin']
665 login_url = reverse_lazy("core:home") 707 login_url = reverse_lazy("core:home")
@@ -689,6 +731,25 @@ class UpdateTopicView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): @@ -689,6 +731,25 @@ class UpdateTopicView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView):
689 context['subjects'] = topic.subject.course.subjects.all() 731 context['subjects'] = topic.subject.course.subjects.all()
690 return context 732 return context
691 733
  734 + def form_valid(self, form):
  735 + self.object = form.save()
  736 +
  737 + self.log_context['topic_id'] = self.object.id
  738 + self.log_context['topic_name'] = self.object.name
  739 + self.log_context['topic_slug'] = self.object.slug
  740 + self.log_context['subject_id'] = self.object.subject.id
  741 + self.log_context['subject_name'] = self.object.subject.name
  742 + self.log_context['subject_slug'] = self.object.subject.slug
  743 + self.log_context['course_id'] = self.object.subject.course.id
  744 + self.log_context['course_name'] = self.object.subject.course.name
  745 + self.log_context['course_slug'] = self.object.subject.course.slug
  746 + self.log_context['course_category_id'] = self.object.subject.course.category.id
  747 + self.log_context['course_category_name'] = self.object.subject.course.category.name
  748 +
  749 + super(UpdateTopicView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  750 +
  751 + return super(UpdateTopicView, self).form_valid(form)
  752 +
692 class CreateSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin, generic.edit.CreateView): 753 class CreateSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin, generic.edit.CreateView):
693 log_component = "course" 754 log_component = "course"
694 log_resource = "subject" 755 log_resource = "subject"
@@ -739,7 +800,11 @@ class CreateSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, Notification @@ -739,7 +800,11 @@ class CreateSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, Notification
739 return super(CreateSubjectView, self).form_valid(form) 800 return super(CreateSubjectView, self).form_valid(form)
740 801
741 802
742 -class UpdateSubjectView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): 803 +class UpdateSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.UpdateView):
  804 + log_component = "course"
  805 + log_resource = "subject"
  806 + log_action = "update"
  807 + log_context = {}
743 808
744 allowed_roles = ['professor', 'system_admin'] 809 allowed_roles = ['professor', 'system_admin']
745 login_url = reverse_lazy("core:home") 810 login_url = reverse_lazy("core:home")
@@ -753,6 +818,22 @@ class UpdateSubjectView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): @@ -753,6 +818,22 @@ class UpdateSubjectView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView):
753 return self.handle_no_permission() 818 return self.handle_no_permission()
754 return super(UpdateSubjectView, self).dispatch(*args, **kwargs) 819 return super(UpdateSubjectView, self).dispatch(*args, **kwargs)
755 820
  821 + def form_valid(self, form):
  822 + self.object = form.save()
  823 +
  824 + self.log_context['subject_id'] = self.object.id
  825 + self.log_context['subject_name'] = self.object.name
  826 + self.log_context['subject_slug'] = self.object.slug
  827 + self.log_context['course_id'] = self.object.course.id
  828 + self.log_context['course_name'] = self.object.course.name
  829 + self.log_context['course_slug'] = self.object.course.slug
  830 + self.log_context['course_category_id'] = self.object.course.category.id
  831 + self.log_context['course_category_name'] = self.object.course.category.name
  832 +
  833 + super(UpdateSubjectView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  834 +
  835 + return super(UpdateSubjectView, self).form_valid(form)
  836 +
756 def get_object(self, queryset=None): 837 def get_object(self, queryset=None):
757 context = get_object_or_404(Subject, slug = self.kwargs.get('slug')) 838 context = get_object_or_404(Subject, slug = self.kwargs.get('slug'))
758 return context 839 return context
@@ -769,7 +850,11 @@ class UpdateSubjectView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): @@ -769,7 +850,11 @@ class UpdateSubjectView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView):
769 context['subjects'] = self.object.course.subjects.all() 850 context['subjects'] = self.object.course.subjects.all()
770 return context 851 return context
771 852
772 -class DeleteSubjectView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): 853 +class DeleteSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.DeleteView):
  854 + log_component = "course"
  855 + log_resource = "subject"
  856 + log_action = "delete"
  857 + log_context = {}
773 858
774 allowed_roles = ['professor', 'system_admin'] 859 allowed_roles = ['professor', 'system_admin']
775 login_url = reverse_lazy("core:home") 860 login_url = reverse_lazy("core:home")
@@ -783,7 +868,6 @@ class DeleteSubjectView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): @@ -783,7 +868,6 @@ class DeleteSubjectView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView):
783 return self.handle_no_permission() 868 return self.handle_no_permission()
784 return super(DeleteSubjectView, self).dispatch(*args, **kwargs) 869 return super(DeleteSubjectView, self).dispatch(*args, **kwargs)
785 870
786 -  
787 def get_context_data(self, **kwargs): 871 def get_context_data(self, **kwargs):
788 context = super(DeleteSubjectView, self).get_context_data(**kwargs) 872 context = super(DeleteSubjectView, self).get_context_data(**kwargs)
789 context['course'] = self.object.course 873 context['course'] = self.object.course
@@ -794,9 +878,21 @@ class DeleteSubjectView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): @@ -794,9 +878,21 @@ class DeleteSubjectView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView):
794 return context 878 return context
795 879
796 def get_success_url(self): 880 def get_success_url(self):
  881 + self.log_context['subject_id'] = self.object.id
  882 + self.log_context['subject_name'] = self.object.name
  883 + self.log_context['subject_slug'] = self.object.slug
  884 + self.log_context['course_id'] = self.object.course.id
  885 + self.log_context['course_name'] = self.object.course.name
  886 + self.log_context['course_slug'] = self.object.course.slug
  887 + self.log_context['course_category_id'] = self.object.course.category.id
  888 + self.log_context['course_category_name'] = self.object.course.category.name
  889 +
  890 + super(DeleteSubjectView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  891 +
797 return reverse_lazy('course:view', kwargs={'slug' : self.object.course.slug}) 892 return reverse_lazy('course:view', kwargs={'slug' : self.object.course.slug})
798 893
799 @login_required 894 @login_required
  895 +@log_decorator("course", "subscribe", "subject")
800 def subscribe_subject(request, slug): 896 def subscribe_subject(request, slug):
801 subject = get_object_or_404(Subject, slug = slug) 897 subject = get_object_or_404(Subject, slug = slug)
802 898
@@ -804,6 +900,18 @@ def subscribe_subject(request, slug): @@ -804,6 +900,18 @@ def subscribe_subject(request, slug):
804 subject.students.add(request.user) 900 subject.students.add(request.user)
805 901
806 if request.user in subject.students.all(): 902 if request.user in subject.students.all():
  903 + log_context = {}
  904 + log_context['subject_id'] = subject.id
  905 + log_context['subject_name'] = subject.name
  906 + log_context['subject_slug'] = subject.slug
  907 + log_context['course_id'] = subject.course.id
  908 + log_context['course_name'] = subject.course.name
  909 + log_context['course_slug'] = subject.course.slug
  910 + log_context['course_category_id'] = subject.course.category.id
  911 + log_context['course_category_name'] = subject.course.category.name
  912 +
  913 + request.log_context = log_context
  914 +
807 return JsonResponse({"status": "ok", "message": _("Successfully subscribed to the subject!")}) 915 return JsonResponse({"status": "ok", "message": _("Successfully subscribed to the subject!")})
808 else: 916 else:
809 return JsonResponse({"status": "erro", "message": _("An error has occured. Could not subscribe to this subject, try again later")}) 917 return JsonResponse({"status": "erro", "message": _("An error has occured. Could not subscribe to this subject, try again later")})
files/static/js/file.js
1 function get_modal_file(url, id, div_content){ 1 function get_modal_file(url, id, div_content){
2 2
3 $.get(url, function (data) { 3 $.get(url, function (data) {
4 - $(div_content).empty(); 4 + $(div_content).detach();
5 $(div_content).append(data); 5 $(div_content).append(data);
6 $(id).modal('show'); 6 $(id).modal('show');
7 }); 7 });
forum/static/js/forum.js
@@ -74,6 +74,8 @@ function setForumCreateFormSubmit(topic) { @@ -74,6 +74,8 @@ function setForumCreateFormSubmit(topic) {
74 success: function (data) { 74 success: function (data) {
75 $(".topic_" + topic).find('.foruns_list').append("<li><i class='fa fa-commenting' aria-hidden='true'></i> <a id='forum_"+data.forum_id+"' href='"+data.url+"'> "+data.name+"</a></li>"); 75 $(".topic_" + topic).find('.foruns_list').append("<li><i class='fa fa-commenting' aria-hidden='true'></i> <a id='forum_"+data.forum_id+"' href='"+data.url+"'> "+data.name+"</a></li>");
76 76
  77 + alertify.success(data.message);
  78 +
77 $("#createForum").modal('hide'); 79 $("#createForum").modal('hide');
78 }, 80 },
79 error: function(data) { 81 error: function(data) {
@@ -221,6 +223,8 @@ function delete_post(url, post) { @@ -221,6 +223,8 @@ function delete_post(url, post) {
221 }, 223 },
222 url: url, 224 url: url,
223 success: function(data) { 225 success: function(data) {
  226 + alertify.success(data);
  227 +
224 $("#post_"+post).remove(); 228 $("#post_"+post).remove();
225 } 229 }
226 }); 230 });
forum/templates/forum/forum_form.html
@@ -15,21 +15,21 @@ @@ -15,21 +15,21 @@
15 <label for="{{ field.auto_id }}">{{ field.label }}</label> 15 <label for="{{ field.auto_id }}">{{ field.label }}</label>
16 {% render_field field %} 16 {% render_field field %}
17 <span class="help-block">{{ field.help_text }}</span> 17 <span class="help-block">{{ field.help_text }}</span>
18 - {% if field.errors %}  
19 - <div class="row">  
20 - <br />  
21 - <div class="alert alert-danger alert-dismissible" role="alert">  
22 - <button type="button" class="close" data-dismiss="alert" aria-label="Close">  
23 - <span aria-hidden="true">&times;</span>  
24 - </button>  
25 - <ul>  
26 - {% for error in field.errors %}  
27 - <li>{{ error }}</li>  
28 - {% endfor %}  
29 - </ul>  
30 - </div> 18 + {% endif %}
  19 + {% if field.errors %}
  20 + <div class="row">
  21 + <br />
  22 + <div class="alert alert-danger alert-dismissible" role="alert">
  23 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  24 + <span aria-hidden="true">&times;</span>
  25 + </button>
  26 + <ul>
  27 + {% for error in field.errors %}
  28 + <li>{{ error }}</li>
  29 + {% endfor %}
  30 + </ul>
31 </div> 31 </div>
32 - {% endif %} 32 + </div>
33 {% endif %} 33 {% endif %}
34 </div> 34 </div>
35 {% endfor %} 35 {% endfor %}
forum/templates/post/post_render.html
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 <a href="javascript:answer('{{ post.id }}', '{% url 'course:forum:reply_post' %}');"> 8 <a href="javascript:answer('{{ post.id }}', '{% url 'course:forum:reply_post' %}');">
9 <i class="material-icons">{% trans 'reply' %}</i> 9 <i class="material-icons">{% trans 'reply' %}</i>
10 </a> 10 </a>
11 - {% if request.user|has_role:'system_admin' or request.user|has_role:'professor' and request.user == post.user %} 11 + {% if request.user|has_role:'system_admin' or request.user == post.user %}
12 {% csrf_token %} 12 {% csrf_token %}
13 <div class="btn-group icon-more-horiz"> 13 <div class="btn-group icon-more-horiz">
14 <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> 14 <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
forum/views.py
@@ -18,7 +18,7 @@ from core.models import Action, Resource @@ -18,7 +18,7 @@ from core.models import Action, Resource
18 18
19 from .forms import ForumForm, PostForm, PostAnswerForm 19 from .forms import ForumForm, PostForm, PostAnswerForm
20 20
21 -from core.mixins import NotificationMixin 21 +from core.mixins import LogMixin, NotificationMixin
22 22
23 """ 23 """
24 Forum Section 24 Forum Section
@@ -44,7 +44,12 @@ class ForumIndex(LoginRequiredMixin, generic.ListView): @@ -44,7 +44,12 @@ class ForumIndex(LoginRequiredMixin, generic.ListView):
44 44
45 return context 45 return context
46 46
47 -class CreateForumView(LoginRequiredMixin, HasRoleMixin, generic.edit.CreateView, NotificationMixin): 47 +class CreateForumView(LoginRequiredMixin, HasRoleMixin, generic.edit.CreateView, LogMixin, NotificationMixin):
  48 + log_component = "forum"
  49 + log_action = "create"
  50 + log_resource = "forum"
  51 + log_context = {}
  52 +
48 allowed_roles = ['professor', 'system_admin'] 53 allowed_roles = ['professor', 'system_admin']
49 54
50 login_url = reverse_lazy("core:home") 55 login_url = reverse_lazy("core:home")
@@ -67,14 +72,36 @@ class CreateForumView(LoginRequiredMixin, HasRoleMixin, generic.edit.CreateView, @@ -67,14 +72,36 @@ class CreateForumView(LoginRequiredMixin, HasRoleMixin, generic.edit.CreateView,
67 super(CreateForumView, self).createNotification("Forum "+ self.object.name + " was created", 72 super(CreateForumView, self).createNotification("Forum "+ self.object.name + " was created",
68 resource_name=self.object.name, resource_link= reverse('course:forum:view', args=[self.object.slug]), 73 resource_name=self.object.name, resource_link= reverse('course:forum:view', args=[self.object.slug]),
69 actor=self.request.user, users = self.object.topic.subject.students.all() ) 74 actor=self.request.user, users = self.object.topic.subject.students.all() )
  75 +
  76 + self.log_context['forum_id'] = self.object.id
  77 + self.log_context['forum_name'] = self.object.name
  78 + self.log_context['topic_id'] = self.object.topic.id
  79 + self.log_context['topic_name'] = self.object.topic.name
  80 + self.log_context['topic_slug'] = self.object.topic.slug
  81 + self.log_context['subject_id'] = self.object.topic.subject.id
  82 + self.log_context['subject_name'] = self.object.topic.subject.name
  83 + self.log_context['subject_slug'] = self.object.topic.subject.slug
  84 + self.log_context['course_id'] = self.object.topic.subject.course.id
  85 + self.log_context['course_name'] = self.object.topic.subject.course.name
  86 + self.log_context['course_slug'] = self.object.topic.subject.course.slug
  87 + self.log_context['course_category_id'] = self.object.topic.subject.course.category.id
  88 + self.log_context['course_category_name'] = self.object.topic.subject.course.category.name
  89 +
  90 + super(CreateForumView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  91 +
70 return self.success_url 92 return self.success_url
71 93
72 def render_forum(request, forum): 94 def render_forum(request, forum):
73 last_forum = get_object_or_404(Forum, id = forum) 95 last_forum = get_object_or_404(Forum, id = forum)
74 96
75 - return JsonResponse({'url': str(reverse_lazy('course:forum:view', args = (), kwargs = {'slug': last_forum.slug})), 'forum_id': str(forum), 'name': str(last_forum.name)}) 97 + return JsonResponse({'url': str(reverse_lazy('course:forum:view', args = (), kwargs = {'slug': last_forum.slug})), 'forum_id': str(forum), 'name': str(last_forum.name), 'message': _('Forum created successfully!')})
  98 +
  99 +class UpdateForumView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView, LogMixin):
  100 + log_component = "forum"
  101 + log_action = "update"
  102 + log_resource = "forum"
  103 + log_context = {}
76 104
77 -class UpdateForumView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView):  
78 allowed_roles = ['professor', 'system_admin'] 105 allowed_roles = ['professor', 'system_admin']
79 106
80 login_url = reverse_lazy("core:home") 107 login_url = reverse_lazy("core:home")
@@ -97,6 +124,22 @@ class UpdateForumView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): @@ -97,6 +124,22 @@ class UpdateForumView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView):
97 124
98 def get_success_url(self): 125 def get_success_url(self):
99 self.success_url = reverse('course:forum:render_edit_forum', args = (self.object.id, )) 126 self.success_url = reverse('course:forum:render_edit_forum', args = (self.object.id, ))
  127 +
  128 + self.log_context['forum_id'] = self.object.id
  129 + self.log_context['forum_name'] = self.object.name
  130 + self.log_context['topic_id'] = self.object.topic.id
  131 + self.log_context['topic_name'] = self.object.topic.name
  132 + self.log_context['topic_slug'] = self.object.topic.slug
  133 + self.log_context['subject_id'] = self.object.topic.subject.id
  134 + self.log_context['subject_name'] = self.object.topic.subject.name
  135 + self.log_context['subject_slug'] = self.object.topic.subject.slug
  136 + self.log_context['course_id'] = self.object.topic.subject.course.id
  137 + self.log_context['course_name'] = self.object.topic.subject.course.name
  138 + self.log_context['course_slug'] = self.object.topic.subject.course.slug
  139 + self.log_context['course_category_id'] = self.object.topic.subject.course.category.id
  140 + self.log_context['course_category_name'] = self.object.topic.subject.course.category.name
  141 +
  142 + super(UpdateForumView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
100 143
101 return self.success_url 144 return self.success_url
102 145
@@ -108,7 +151,12 @@ def render_edit_forum(request, forum): @@ -108,7 +151,12 @@ def render_edit_forum(request, forum):
108 151
109 return render(request, 'forum/render_forum.html', context) 152 return render(request, 'forum/render_forum.html', context)
110 153
111 -class ForumDeleteView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): 154 +class ForumDeleteView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView, LogMixin):
  155 + log_component = "forum"
  156 + log_action = "delete"
  157 + log_resource = "forum"
  158 + log_context = {}
  159 +
112 allowed_roles = ['professor', 'system_admin'] 160 allowed_roles = ['professor', 'system_admin']
113 161
114 login_url = reverse_lazy("core:home") 162 login_url = reverse_lazy("core:home")
@@ -116,7 +164,6 @@ class ForumDeleteView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): @@ -116,7 +164,6 @@ class ForumDeleteView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView):
116 164
117 model = Forum 165 model = Forum
118 pk_url_kwarg = 'pk' 166 pk_url_kwarg = 'pk'
119 - success_url = reverse_lazy('course:forum:deleted_forum')  
120 167
121 def dispatch(self, *args, **kwargs): 168 def dispatch(self, *args, **kwargs):
122 forum = get_object_or_404(Forum, id = self.kwargs.get('pk')) 169 forum = get_object_or_404(Forum, id = self.kwargs.get('pk'))
@@ -126,10 +173,34 @@ class ForumDeleteView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): @@ -126,10 +173,34 @@ class ForumDeleteView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView):
126 173
127 return super(ForumDeleteView, self).dispatch(*args, **kwargs) 174 return super(ForumDeleteView, self).dispatch(*args, **kwargs)
128 175
  176 + def get_success_url(self):
  177 + self.log_context['forum_id'] = self.object.id
  178 + self.log_context['forum_name'] = self.object.name
  179 + self.log_context['topic_id'] = self.object.topic.id
  180 + self.log_context['topic_name'] = self.object.topic.name
  181 + self.log_context['topic_slug'] = self.object.topic.slug
  182 + self.log_context['subject_id'] = self.object.topic.subject.id
  183 + self.log_context['subject_name'] = self.object.topic.subject.name
  184 + self.log_context['subject_slug'] = self.object.topic.subject.slug
  185 + self.log_context['course_id'] = self.object.topic.subject.course.id
  186 + self.log_context['course_name'] = self.object.topic.subject.course.name
  187 + self.log_context['course_slug'] = self.object.topic.subject.course.slug
  188 + self.log_context['course_category_id'] = self.object.topic.subject.course.category.id
  189 + self.log_context['course_category_name'] = self.object.topic.subject.course.category.name
  190 +
  191 + super(ForumDeleteView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  192 +
  193 + return reverse_lazy('course:forum:deleted_forum')
  194 +
129 def forum_deleted(request): 195 def forum_deleted(request):
130 return HttpResponse(_("Forum deleted successfully.")) 196 return HttpResponse(_("Forum deleted successfully."))
131 197
132 -class ForumDetailView(LoginRequiredMixin, generic.DetailView): 198 +class ForumDetailView(LoginRequiredMixin, LogMixin, generic.DetailView):
  199 + log_component = "forum"
  200 + log_action = "viewed"
  201 + log_resource = "forum"
  202 + log_context = {}
  203 +
133 login_url = reverse_lazy("core:home") 204 login_url = reverse_lazy("core:home")
134 redirect_field_name = 'next' 205 redirect_field_name = 'next'
135 206
@@ -143,6 +214,22 @@ class ForumDetailView(LoginRequiredMixin, generic.DetailView): @@ -143,6 +214,22 @@ class ForumDetailView(LoginRequiredMixin, generic.DetailView):
143 if(not has_object_permission('view_forum', self.request.user, forum)): 214 if(not has_object_permission('view_forum', self.request.user, forum)):
144 return self.handle_no_permission() 215 return self.handle_no_permission()
145 216
  217 + self.log_context['forum_id'] = forum.id
  218 + self.log_context['forum_name'] = forum.name
  219 + self.log_context['topic_id'] = forum.topic.id
  220 + self.log_context['topic_name'] = forum.topic.name
  221 + self.log_context['topic_slug'] = forum.topic.slug
  222 + self.log_context['subject_id'] = forum.topic.subject.id
  223 + self.log_context['subject_name'] = forum.topic.subject.name
  224 + self.log_context['subject_slug'] = forum.topic.subject.slug
  225 + self.log_context['course_id'] = forum.topic.subject.course.id
  226 + self.log_context['course_name'] = forum.topic.subject.course.name
  227 + self.log_context['course_slug'] = forum.topic.subject.course.slug
  228 + self.log_context['course_category_id'] = forum.topic.subject.course.category.id
  229 + self.log_context['course_category_name'] = forum.topic.subject.course.category.name
  230 +
  231 + super(ForumDetailView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  232 +
146 return super(ForumDetailView, self).dispatch(*args, **kwargs) 233 return super(ForumDetailView, self).dispatch(*args, **kwargs)
147 234
148 def get_context_data(self, **kwargs): 235 def get_context_data(self, **kwargs):
@@ -195,7 +282,12 @@ def load_posts(request, forum_id): @@ -195,7 +282,12 @@ def load_posts(request, forum_id):
195 282
196 return JsonResponse({'num_pages': paginator.num_pages, 'page': page_obj.number, 'btn_text': _('Load more posts'), 'html': html}) 283 return JsonResponse({'num_pages': paginator.num_pages, 'page': page_obj.number, 'btn_text': _('Load more posts'), 'html': html})
197 284
198 -class CreatePostView(LoginRequiredMixin, generic.edit.CreateView, NotificationMixin): 285 +class CreatePostView(LoginRequiredMixin, generic.edit.CreateView, LogMixin, NotificationMixin):
  286 + log_component = "forum"
  287 + log_action = "create"
  288 + log_resource = "post"
  289 + log_context = {}
  290 +
199 login_url = reverse_lazy("core:home") 291 login_url = reverse_lazy("core:home")
200 redirect_field_name = 'next' 292 redirect_field_name = 'next'
201 293
@@ -211,6 +303,23 @@ class CreatePostView(LoginRequiredMixin, generic.edit.CreateView, NotificationMi @@ -211,6 +303,23 @@ class CreatePostView(LoginRequiredMixin, generic.edit.CreateView, NotificationMi
211 resource_slug = self.object.forum.slug, actor=self.request.user, users= self.object.forum.topic.subject.students.all(), 303 resource_slug = self.object.forum.slug, actor=self.request.user, users= self.object.forum.topic.subject.students.all(),
212 resource_link = reverse('course:forum:view', args=[self.object.forum.slug])) 304 resource_link = reverse('course:forum:view', args=[self.object.forum.slug]))
213 305
  306 + self.log_context['post_id'] = self.object.id
  307 + self.log_context['forum_id'] = self.object.forum.id
  308 + self.log_context['forum_name'] = self.object.forum.name
  309 + self.log_context['topic_id'] = self.object.forum.topic.id
  310 + self.log_context['topic_name'] = self.object.forum.topic.name
  311 + self.log_context['topic_slug'] = self.object.forum.topic.slug
  312 + self.log_context['subject_id'] = self.object.forum.topic.subject.id
  313 + self.log_context['subject_name'] = self.object.forum.topic.subject.name
  314 + self.log_context['subject_slug'] = self.object.forum.topic.subject.slug
  315 + self.log_context['course_id'] = self.object.forum.topic.subject.course.id
  316 + self.log_context['course_name'] = self.object.forum.topic.subject.course.name
  317 + self.log_context['course_slug'] = self.object.forum.topic.subject.course.slug
  318 + self.log_context['course_category_id'] = self.object.forum.topic.subject.course.category.id
  319 + self.log_context['course_category_name'] = self.object.forum.topic.subject.course.category.name
  320 +
  321 + super(CreatePostView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  322 +
214 return super(CreatePostView, self).form_valid(form) 323 return super(CreatePostView, self).form_valid(form)
215 324
216 def get_success_url(self): 325 def get_success_url(self):
@@ -228,7 +337,12 @@ def render_post(request, post): @@ -228,7 +337,12 @@ def render_post(request, post):
228 337
229 return JsonResponse({'new_id': last_post.id, 'html': html}) 338 return JsonResponse({'new_id': last_post.id, 'html': html})
230 339
231 -class PostUpdateView(LoginRequiredMixin, generic.UpdateView): 340 +class PostUpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView):
  341 + log_component = "forum"
  342 + log_action = "update"
  343 + log_resource = "post"
  344 + log_context = {}
  345 +
232 login_url = reverse_lazy("core:home") 346 login_url = reverse_lazy("core:home")
233 redirect_field_name = 'next' 347 redirect_field_name = 'next'
234 348
@@ -236,18 +350,66 @@ class PostUpdateView(LoginRequiredMixin, generic.UpdateView): @@ -236,18 +350,66 @@ class PostUpdateView(LoginRequiredMixin, generic.UpdateView):
236 model = Post 350 model = Post
237 template_name = "post/post_update_form.html" 351 template_name = "post/post_update_form.html"
238 352
  353 + def form_valid(self, form):
  354 + self.object = form.save()
  355 +
  356 + self.log_context['post_id'] = self.object.id
  357 + self.log_context['forum_id'] = self.object.forum.id
  358 + self.log_context['forum_name'] = self.object.forum.name
  359 + self.log_context['topic_id'] = self.object.forum.topic.id
  360 + self.log_context['topic_name'] = self.object.forum.topic.name
  361 + self.log_context['topic_slug'] = self.object.forum.topic.slug
  362 + self.log_context['subject_id'] = self.object.forum.topic.subject.id
  363 + self.log_context['subject_name'] = self.object.forum.topic.subject.name
  364 + self.log_context['subject_slug'] = self.object.forum.topic.subject.slug
  365 + self.log_context['course_id'] = self.object.forum.topic.subject.course.id
  366 + self.log_context['course_name'] = self.object.forum.topic.subject.course.name
  367 + self.log_context['course_slug'] = self.object.forum.topic.subject.course.slug
  368 + self.log_context['course_category_id'] = self.object.forum.topic.subject.course.category.id
  369 + self.log_context['course_category_name'] = self.object.forum.topic.subject.course.category.name
  370 +
  371 + super(PostUpdateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  372 +
  373 + return super(PostUpdateView, self).form_valid(form)
  374 +
239 def get_success_url(self): 375 def get_success_url(self):
240 self.success_url = reverse('course:forum:render_post', args = (self.object.id, )) 376 self.success_url = reverse('course:forum:render_post', args = (self.object.id, ))
241 377
242 return self.success_url 378 return self.success_url
243 379
244 -class PostDeleteView(LoginRequiredMixin, generic.DeleteView): 380 +class PostDeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView):
  381 + log_component = "forum"
  382 + log_action = "delete"
  383 + log_resource = "post"
  384 + log_context = {}
  385 +
245 login_url = reverse_lazy("core:home") 386 login_url = reverse_lazy("core:home")
246 redirect_field_name = 'next' 387 redirect_field_name = 'next'
247 388
248 model = Post 389 model = Post
249 pk_url_kwarg = 'pk' 390 pk_url_kwarg = 'pk'
250 - success_url = reverse_lazy('course:forum:deleted_post') 391 +
  392 + def get_success_url(self):
  393 + self.success_url = reverse_lazy('course:forum:deleted_post')
  394 +
  395 + self.log_context['post_id'] = self.object.id
  396 + self.log_context['forum_id'] = self.object.forum.id
  397 + self.log_context['forum_name'] = self.object.forum.name
  398 + self.log_context['topic_id'] = self.object.forum.topic.id
  399 + self.log_context['topic_name'] = self.object.forum.topic.name
  400 + self.log_context['topic_slug'] = self.object.forum.topic.slug
  401 + self.log_context['subject_id'] = self.object.forum.topic.subject.id
  402 + self.log_context['subject_name'] = self.object.forum.topic.subject.name
  403 + self.log_context['subject_slug'] = self.object.forum.topic.subject.slug
  404 + self.log_context['course_id'] = self.object.forum.topic.subject.course.id
  405 + self.log_context['course_name'] = self.object.forum.topic.subject.course.name
  406 + self.log_context['course_slug'] = self.object.forum.topic.subject.course.slug
  407 + self.log_context['course_category_id'] = self.object.forum.topic.subject.course.category.id
  408 + self.log_context['course_category_name'] = self.object.forum.topic.subject.course.category.name
  409 +
  410 + super(PostDeleteView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  411 +
  412 + return self.success_url
251 413
252 def post_deleted(request): 414 def post_deleted(request):
253 return HttpResponse(_("Post deleted successfully.")) 415 return HttpResponse(_("Post deleted successfully."))
@@ -308,7 +470,12 @@ class PostAnswerIndex(LoginRequiredMixin, generic.ListView): @@ -308,7 +470,12 @@ class PostAnswerIndex(LoginRequiredMixin, generic.ListView):
308 470
309 return context 471 return context
310 472
311 -class CreatePostAnswerView(LoginRequiredMixin, generic.edit.CreateView): 473 +class CreatePostAnswerView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
  474 + log_component = "forum"
  475 + log_action = "create"
  476 + log_resource = "post_answer"
  477 + log_context = {}
  478 +
312 login_url = reverse_lazy("core:home") 479 login_url = reverse_lazy("core:home")
313 redirect_field_name = 'next' 480 redirect_field_name = 'next'
314 481
@@ -321,6 +488,25 @@ class CreatePostAnswerView(LoginRequiredMixin, generic.edit.CreateView): @@ -321,6 +488,25 @@ class CreatePostAnswerView(LoginRequiredMixin, generic.edit.CreateView):
321 488
322 self.object.save() 489 self.object.save()
323 490
  491 + self.log_context['post_answer_id'] = self.object.id
  492 + self.log_context['post_id'] = self.object.post.id
  493 + self.log_context['post_user_id'] = self.object.post.user.id
  494 + self.log_context['post_user_name'] = self.object.post.user.name
  495 + self.log_context['forum_id'] = self.object.post.forum.id
  496 + self.log_context['forum_name'] = self.object.post.forum.name
  497 + self.log_context['topic_id'] = self.object.post.forum.topic.id
  498 + self.log_context['topic_name'] = self.object.post.forum.topic.name
  499 + self.log_context['topic_slug'] = self.object.post.forum.topic.slug
  500 + self.log_context['subject_id'] = self.object.post.forum.topic.subject.id
  501 + self.log_context['subject_name'] = self.object.post.forum.topic.subject.name
  502 + self.log_context['subject_slug'] = self.object.post.forum.topic.subject.slug
  503 + self.log_context['course_id'] = self.object.post.forum.topic.subject.course.id
  504 + self.log_context['course_name'] = self.object.post.forum.topic.subject.course.name
  505 + self.log_context['course_slug'] = self.object.post.forum.topic.subject.course.slug
  506 + self.log_context['course_category_id'] = self.object.post.forum.topic.subject.course.category.id
  507 + self.log_context['course_category_name'] = self.object.post.forum.topic.subject.course.category.name
  508 +
  509 + super(CreatePostAnswerView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
324 510
325 return super(CreatePostAnswerView, self).form_valid(form) 511 return super(CreatePostAnswerView, self).form_valid(form)
326 512
@@ -339,7 +525,12 @@ def render_post_answer(request, answer): @@ -339,7 +525,12 @@ def render_post_answer(request, answer):
339 525
340 return JsonResponse({'new_id': last_answer.id, 'html': html}) 526 return JsonResponse({'new_id': last_answer.id, 'html': html})
341 527
342 -class PostAnswerUpdateView(LoginRequiredMixin, generic.UpdateView): 528 +class PostAnswerUpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView):
  529 + log_component = "forum"
  530 + log_action = "update"
  531 + log_resource = "post_answer"
  532 + log_context = {}
  533 +
343 login_url = reverse_lazy("core:home") 534 login_url = reverse_lazy("core:home")
344 redirect_field_name = 'next' 535 redirect_field_name = 'next'
345 536
@@ -350,16 +541,65 @@ class PostAnswerUpdateView(LoginRequiredMixin, generic.UpdateView): @@ -350,16 +541,65 @@ class PostAnswerUpdateView(LoginRequiredMixin, generic.UpdateView):
350 541
351 def get_success_url(self): 542 def get_success_url(self):
352 self.success_url = reverse('course:forum:render_post_answer', args = (self.object.id, )) 543 self.success_url = reverse('course:forum:render_post_answer', args = (self.object.id, ))
  544 +
  545 + self.log_context['post_answer_id'] = self.object.id
  546 + self.log_context['post_id'] = self.object.post.id
  547 + self.log_context['post_user_id'] = self.object.post.user.id
  548 + self.log_context['post_user_name'] = self.object.post.user.name
  549 + self.log_context['forum_id'] = self.object.post.forum.id
  550 + self.log_context['forum_name'] = self.object.post.forum.name
  551 + self.log_context['topic_id'] = self.object.post.forum.topic.id
  552 + self.log_context['topic_name'] = self.object.post.forum.topic.name
  553 + self.log_context['topic_slug'] = self.object.post.forum.topic.slug
  554 + self.log_context['subject_id'] = self.object.post.forum.topic.subject.id
  555 + self.log_context['subject_name'] = self.object.post.forum.topic.subject.name
  556 + self.log_context['subject_slug'] = self.object.post.forum.topic.subject.slug
  557 + self.log_context['course_id'] = self.object.post.forum.topic.subject.course.id
  558 + self.log_context['course_name'] = self.object.post.forum.topic.subject.course.name
  559 + self.log_context['course_slug'] = self.object.post.forum.topic.subject.course.slug
  560 + self.log_context['course_category_id'] = self.object.post.forum.topic.subject.course.category.id
  561 + self.log_context['course_category_name'] = self.object.post.forum.topic.subject.course.category.name
  562 +
  563 + super(PostAnswerUpdateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
353 564
354 return self.success_url 565 return self.success_url
355 566
356 -class PostAnswerDeleteView(LoginRequiredMixin, generic.DeleteView): 567 +class PostAnswerDeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView):
  568 + log_component = "forum"
  569 + log_action = "delete"
  570 + log_resource = "post_answer"
  571 + log_context = {}
  572 +
357 login_url = reverse_lazy("core:home") 573 login_url = reverse_lazy("core:home")
358 redirect_field_name = 'next' 574 redirect_field_name = 'next'
359 575
360 model = PostAnswer 576 model = PostAnswer
361 - pk_url_kwarg = 'pk'  
362 - success_url = reverse_lazy('course:forum:deleted_answer') 577 + pk_url_kwarg = 'pk'
  578 +
  579 + def get_success_url(self):
  580 + self.success_url = reverse_lazy('course:forum:deleted_answer')
  581 +
  582 + self.log_context['post_answer_id'] = self.object.id
  583 + self.log_context['post_id'] = self.object.post.id
  584 + self.log_context['post_user_id'] = self.object.post.user.id
  585 + self.log_context['post_user_name'] = self.object.post.user.name
  586 + self.log_context['forum_id'] = self.object.post.forum.id
  587 + self.log_context['forum_name'] = self.object.post.forum.name
  588 + self.log_context['topic_id'] = self.object.post.forum.topic.id
  589 + self.log_context['topic_name'] = self.object.post.forum.topic.name
  590 + self.log_context['topic_slug'] = self.object.post.forum.topic.slug
  591 + self.log_context['subject_id'] = self.object.post.forum.topic.subject.id
  592 + self.log_context['subject_name'] = self.object.post.forum.topic.subject.name
  593 + self.log_context['subject_slug'] = self.object.post.forum.topic.subject.slug
  594 + self.log_context['course_id'] = self.object.post.forum.topic.subject.course.id
  595 + self.log_context['course_name'] = self.object.post.forum.topic.subject.course.name
  596 + self.log_context['course_slug'] = self.object.post.forum.topic.subject.course.slug
  597 + self.log_context['course_category_id'] = self.object.post.forum.topic.subject.course.category.id
  598 + self.log_context['course_category_name'] = self.object.post.forum.topic.subject.course.category.name
  599 +
  600 + super(PostAnswerDeleteView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  601 +
  602 + return self.success_url
363 603
364 def answer_deleted(request): 604 def answer_deleted(request):
365 return HttpResponse(_("Post answer deleted successfully.")) 605 return HttpResponse(_("Post answer deleted successfully."))
366 \ No newline at end of file 606 \ No newline at end of file
links/static/js/links.js
1 function get_modal_link(url, id,div_content){ 1 function get_modal_link(url, id,div_content){
2 $.get(url, function (data) { 2 $.get(url, function (data) {
3 - $(div_content).empty(); 3 + $(div_content).detach();
4 $(div_content).append(data); 4 $(div_content).append(data);
5 $(id).modal('show'); 5 $(id).modal('show');
6 }); 6 });
requirements.txt
  1 +beautifulsoup4==4.5.1
1 click==6.6 2 click==6.6
2 decorator==4.0.10 3 decorator==4.0.10
3 deps==0.1.0 4 deps==0.1.0
@@ -10,18 +11,22 @@ django-floppyforms==1.7.0 @@ -10,18 +11,22 @@ django-floppyforms==1.7.0
10 django-modalview==0.1.5 11 django-modalview==0.1.5
11 django-role-permissions==1.2.1 12 django-role-permissions==1.2.1
12 django-s3direct==0.4.2 13 django-s3direct==0.4.2
  14 +django-summernote==0.8.6
13 django-widget-tweaks==1.4.1 15 django-widget-tweaks==1.4.1
  16 +django-wysiwyg==0.8.0
14 djangorestframework==3.4.6 17 djangorestframework==3.4.6
15 gunicorn==19.6.0 18 gunicorn==19.6.0
  19 +itsdangerous==0.24
16 Jinja2==2.8 20 Jinja2==2.8
  21 +lxml==3.6.4
17 MarkupSafe==0.23 22 MarkupSafe==0.23
18 Pillow==3.3.1 23 Pillow==3.3.1
19 psycopg2==2.6.2 24 psycopg2==2.6.2
20 pycpfcnpj==1.0.2 25 pycpfcnpj==1.0.2
  26 +requests==2.11.1
21 six==1.10.0 27 six==1.10.0
  28 +slugify==0.0.1
22 validators==0.11.0 29 validators==0.11.0
  30 +virtualenv==15.0.3
23 Werkzeug==0.11.11 31 Werkzeug==0.11.11
24 whitenoise==3.2.2 32 whitenoise==3.2.2
25 -beautifulsoup4==4.5.1  
26 -lxml==3.6.4  
27 -requests==2.11.1