Commit 3fe44fc09c899c27c80f10f7c07a9003f106ca3b
1 parent
a4d0a0ff
Exists in
master
and in
5 other branches
conflix
Showing
20 changed files
with
484 additions
and
69 deletions
Show diff stats
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
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
courses/templates/subject/form_view_teacher.html
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
courses/templates/topic/index.html
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">×</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">×</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 |