diff --git a/amadeus/settings.py b/amadeus/settings.py index 438c378..e733a04 100644 --- a/amadeus/settings.py +++ b/amadeus/settings.py @@ -46,6 +46,7 @@ INSTALLED_APPS = [ 'rest_framework', 'django_bootstrap_breadcrumbs', 's3direct', + 'django_summernote', 'users', 'core', @@ -225,7 +226,59 @@ S3DIRECT_DESTINATIONS = { # FILE UPLOAD MAX_UPLOAD_SIZE = 10485760 +SUMMERNOTE_CONFIG = { + # Using SummernoteWidget - iframe mode + 'iframe': True, # or set False to use SummernoteInplaceWidget - no iframe mode + + # Using Summernote Air-mode + 'airMode': False, + + # Use native HTML tags (``, ``, ...) instead of style attributes + # (Firefox, Chrome only) + 'styleWithTags': True, + + # Set text direction : 'left to right' is default. + 'direction': 'ltr', + + # Change editor size + 'width': '100%', + 'height': '480', + + # Use proper language setting automatically (default) + 'lang': None, + + # Or, set editor language/locale forcely + 'lang_matches': { + 'pt': 'pt-BR', + }, + + # Customize toolbar buttons + 'toolbar': [ + ['style', ['style']], + ['font', ['bold', 'italic', 'underline', 'superscript', 'subscript', + 'strikethrough', 'clear']], + ['fontname', ['fontname']], + ['fontsize', ['fontsize']], + ['color', ['color']], + ['para', ['ul', 'ol', 'paragraph']], + ['height', ['height']], + ['table', ['table']], + ['insert', ['link', 'picture', 'video', 'hr']], + ['view', ['fullscreen', 'codeview']], + ['help', ['help']], + ], + + # Need authentication while uploading attachments. + 'attachment_require_authentication': True, + + # Set `upload_to` function for attachments. + #'attachment_upload_to': my_custom_upload_to_func(), + + + +} + try: from .local_settings import * except ImportError: - pass + pass \ No newline at end of file diff --git a/amadeus/urls.py b/amadeus/urls.py index 52845ec..2f3745e 100644 --- a/amadeus/urls.py +++ b/amadeus/urls.py @@ -28,6 +28,7 @@ urlpatterns = [ #S3Direct url(r'^s3direct/', include('s3direct.urls')), + url(r'^summernote/', include('django_summernote.urls')), ] urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT) diff --git a/core/mixins.py b/core/mixins.py index 6c82977..57214e9 100644 --- a/core/mixins.py +++ b/core/mixins.py @@ -34,9 +34,6 @@ class LogMixin(object): else: action_resource = action_resource[0] - print(context) - print(json.dumps(context)) - log = Log() log.user = actor log.context = json.dumps(context) diff --git a/courses/forms.py b/courses/forms.py index 4f32ac2..ae3a796 100644 --- a/courses/forms.py +++ b/courses/forms.py @@ -2,7 +2,7 @@ from django import forms from django.utils.translation import ugettext_lazy as _ from .models import CourseCategory, Course, Subject, Topic, ActivityFile, Activity, FileMaterial, LinkMaterial from s3direct.widgets import S3DirectWidget - +from django_summernote.widgets import SummernoteWidget class CategoryCourseForm(forms.ModelForm): @@ -79,8 +79,8 @@ class CourseForm(forms.ModelForm): widgets = { 'categoy': forms.Select(), - 'objectivies': forms.Textarea(attrs={'cols': 80, 'rows': 5}), - 'content': forms.Textarea(attrs={'cols': 80, 'rows': 5}), + 'objectivies': SummernoteWidget(attrs={'cols': 80, 'rows': 5}), + 'content': SummernoteWidget(attrs={'cols': 80, 'rows': 5}), } class UpdateCourseForm(CourseForm): @@ -120,8 +120,8 @@ class UpdateCourseForm(CourseForm): } widgets = { 'categoy': forms.Select(), - 'objectivies': forms.Textarea(attrs={'cols': 80, 'rows': 5}), - 'content': forms.Textarea(attrs={'cols': 80, 'rows': 5}), + 'objectivies': SummernoteWidget(attrs={'cols': 80, 'rows': 5}), + 'content': SummernoteWidget(attrs={'cols': 80, 'rows': 5}), } class SubjectForm(forms.ModelForm): @@ -143,6 +143,9 @@ class SubjectForm(forms.ModelForm): 'end_date': _('End date of the subject'), 'visible': _('Is the subject visible?'), } + widgets = { + 'description':SummernoteWidget(), + } class TopicForm(forms.ModelForm): @@ -157,6 +160,9 @@ class TopicForm(forms.ModelForm): 'name': _("Topic's name"), 'description': _("Topic's description"), } + widgets = { + 'description':SummernoteWidget(), + } class ActivityFileForm(forms.ModelForm): name = forms.CharField( diff --git a/courses/static/js/topic_editation_presentation.js b/courses/static/js/topic_editation_presentation.js index 171aa34..73bf889 100644 --- a/courses/static/js/topic_editation_presentation.js +++ b/courses/static/js/topic_editation_presentation.js @@ -5,7 +5,8 @@ function show_editation(id_topic){ $(".presentation_"+ id_topic).css('display','none'); $(".editation_"+ id_topic).css('display','block'); }; - function show_presentation(id_topic){ + +function show_presentation(id_topic){ $(".editation_"+ id_topic).css('display','none'); $(".presentation_"+ id_topic).css('display','block'); }; diff --git a/courses/templates/course/course_card.html b/courses/templates/course/course_card.html index 59ce272..2f39e0e 100644 --- a/courses/templates/course/course_card.html +++ b/courses/templates/course/course_card.html @@ -38,7 +38,7 @@

{% trans 'Description' %}: - {{course.content}} + {{course.content | safe }}

diff --git a/courses/templates/course/view.html b/courses/templates/course/view.html index 879c426..4917e99 100644 --- a/courses/templates/course/view.html +++ b/courses/templates/course/view.html @@ -98,7 +98,7 @@

{% trans 'Description' %}: - {{ course.objectivies }} + {{ course.objectivies |safe }}

@@ -174,7 +174,7 @@

{% trans "Description" %}: - {{subject.description}} + {{subject.description | safe}}

diff --git a/courses/templates/subject/form_view_student.html b/courses/templates/subject/form_view_student.html index 0451308..0c9ee20 100644 --- a/courses/templates/subject/form_view_student.html +++ b/courses/templates/subject/form_view_student.html @@ -27,7 +27,7 @@

- {{topic.description|linebreaks}} + {{topic.description|safe}}

diff --git a/courses/templates/subject/form_view_teacher.html b/courses/templates/subject/form_view_teacher.html index 04367bc..73021df 100644 --- a/courses/templates/subject/form_view_teacher.html +++ b/courses/templates/subject/form_view_teacher.html @@ -39,7 +39,7 @@

- {{topic.description|linebreaks}} + {{topic.description|safe}}

diff --git a/courses/templates/subject/index.html b/courses/templates/subject/index.html index 62b31a2..6f3dd47 100644 --- a/courses/templates/subject/index.html +++ b/courses/templates/subject/index.html @@ -75,7 +75,7 @@ {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}

{% trans "Description" %}: - {{subject.description|linebreaks}} + {{subject.description|safe}}

diff --git a/courses/templates/subject_category/index.html b/courses/templates/subject_category/index.html index 091f223..3c94d96 100644 --- a/courses/templates/subject_category/index.html +++ b/courses/templates/subject_category/index.html @@ -58,7 +58,7 @@

- {{subject.description|linebreaks}} + {{subject.description| safe }}

diff --git a/courses/templates/topic/index.html b/courses/templates/topic/index.html index 3c9659c..d97cf21 100644 --- a/courses/templates/topic/index.html +++ b/courses/templates/topic/index.html @@ -77,7 +77,7 @@

- {{topic.description|linebreaks}} + {{topic.description|safe}}

diff --git a/courses/views.py b/courses/views.py index 42a4349..b571bf5 100644 --- a/courses/views.py +++ b/courses/views.py @@ -284,21 +284,12 @@ class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.Delet redirect_field_name = 'next' model = Course template_name = 'course/delete.html' - success_url = reverse_lazy('course:manage') def dispatch(self, *args, **kwargs): course = get_object_or_404(Course, slug = self.kwargs.get('slug')) if(not has_object_permission('delete_course', self.request.user, course)): return self.handle_no_permission() - self.log_context['course_id'] = course.id - self.log_context['course_name'] = course.name - self.log_context['course_slug'] = course.slug - self.log_context['course_category_id'] = course.category.id - self.log_context['course_category_name'] = course.category.name - - super(DeleteCourseView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) - return super(DeleteCourseView, self).dispatch(*args, **kwargs) def get_context_data(self, **kwargs): @@ -314,6 +305,17 @@ class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.Delet return context + def get_success_url(self): + self.log_context['course_id'] = self.object.id + self.log_context['course_name'] = self.object.name + self.log_context['course_slug'] = self.object.slug + self.log_context['course_category_id'] = self.object.category.id + self.log_context['course_category_name'] = self.object.category.name + + super(DeleteCourseView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) + + return reverse_lazy('course:manage') + class CourseView(LogMixin, NotificationMixin, generic.DetailView): log_component = "courses" @@ -586,7 +588,11 @@ class UploadMaterialView(LoginRequiredMixin, generic.edit.CreateView): return self.success_url -class TopicsView(LoginRequiredMixin, generic.ListView): +class TopicsView(LoginRequiredMixin, LogMixin, generic.ListView): + log_component = "course" + log_resource = "topic" + log_action = "viewed" + log_context = {} login_url = reverse_lazy("core:home") redirect_field_name = 'next' @@ -600,6 +606,20 @@ class TopicsView(LoginRequiredMixin, generic.ListView): if(not has_object_permission('view_topic', self.request.user, topic)): return self.handle_no_permission() + self.log_context['topic_id'] = topic.id + self.log_context['topic_name'] = topic.name + self.log_context['topic_slug'] = topic.slug + self.log_context['subject_id'] = topic.subject.id + self.log_context['subject_name'] = topic.subject.name + self.log_context['subject_slug'] = topic.subject.slug + self.log_context['course_id'] = topic.subject.course.id + self.log_context['course_name'] = topic.subject.course.name + self.log_context['course_slug'] = topic.subject.course.slug + self.log_context['course_category_id'] = topic.subject.course.category.id + self.log_context['course_category_name'] = topic.subject.course.category.name + + super(TopicsView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) + return super(TopicsView, self).dispatch(*args, **kwargs) def get_queryset(self): @@ -626,7 +646,11 @@ class TopicsView(LoginRequiredMixin, generic.ListView): return context -class CreateTopicView(LoginRequiredMixin, HasRoleMixin, NotificationMixin, generic.edit.CreateView): +class CreateTopicView(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin, generic.edit.CreateView): + log_component = "course" + log_resource = "topic" + log_action = "create" + log_context = {} allowed_roles = ['professor', 'system_admin'] login_url = reverse_lazy("core:home") @@ -656,10 +680,28 @@ class CreateTopicView(LoginRequiredMixin, HasRoleMixin, NotificationMixin, gener super(CreateTopicView, self).createNotification("Topic "+ self.object.name + " was created", resource_name=self.object.name, resource_link= reverse('course:view_topic',args=[self.object.slug]), actor=self.request.user, users = self.object.subject.course.students.all() ) + + self.log_context['topic_id'] = self.object.id + self.log_context['topic_name'] = self.object.name + self.log_context['topic_slug'] = self.object.slug + self.log_context['subject_id'] = self.object.subject.id + self.log_context['subject_name'] = self.object.subject.name + self.log_context['subject_slug'] = self.object.subject.slug + self.log_context['course_id'] = self.object.subject.course.id + self.log_context['course_name'] = self.object.subject.course.name + self.log_context['course_slug'] = self.object.subject.course.slug + self.log_context['course_category_id'] = self.object.subject.course.category.id + self.log_context['course_category_name'] = self.object.subject.course.category.name + + super(CreateTopicView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) return super(CreateTopicView, self).form_valid(form) -class UpdateTopicView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): +class UpdateTopicView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.UpdateView): + log_component = "course" + log_resource = "topic" + log_action = "create" + log_context = {} allowed_roles = ['professor','system_admin'] login_url = reverse_lazy("core:home") @@ -689,6 +731,25 @@ class UpdateTopicView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): context['subjects'] = topic.subject.course.subjects.all() return context + def form_valid(self, form): + self.object = form.save() + + self.log_context['topic_id'] = self.object.id + self.log_context['topic_name'] = self.object.name + self.log_context['topic_slug'] = self.object.slug + self.log_context['subject_id'] = self.object.subject.id + self.log_context['subject_name'] = self.object.subject.name + self.log_context['subject_slug'] = self.object.subject.slug + self.log_context['course_id'] = self.object.subject.course.id + self.log_context['course_name'] = self.object.subject.course.name + self.log_context['course_slug'] = self.object.subject.course.slug + self.log_context['course_category_id'] = self.object.subject.course.category.id + self.log_context['course_category_name'] = self.object.subject.course.category.name + + super(UpdateTopicView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) + + return super(UpdateTopicView, self).form_valid(form) + class CreateSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin, generic.edit.CreateView): log_component = "course" log_resource = "subject" @@ -739,7 +800,11 @@ class CreateSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, Notification return super(CreateSubjectView, self).form_valid(form) -class UpdateSubjectView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): +class UpdateSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.UpdateView): + log_component = "course" + log_resource = "subject" + log_action = "update" + log_context = {} allowed_roles = ['professor', 'system_admin'] login_url = reverse_lazy("core:home") @@ -753,6 +818,22 @@ class UpdateSubjectView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): return self.handle_no_permission() return super(UpdateSubjectView, self).dispatch(*args, **kwargs) + def form_valid(self, form): + self.object = form.save() + + self.log_context['subject_id'] = self.object.id + self.log_context['subject_name'] = self.object.name + self.log_context['subject_slug'] = self.object.slug + self.log_context['course_id'] = self.object.course.id + self.log_context['course_name'] = self.object.course.name + self.log_context['course_slug'] = self.object.course.slug + self.log_context['course_category_id'] = self.object.course.category.id + self.log_context['course_category_name'] = self.object.course.category.name + + super(UpdateSubjectView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) + + return super(UpdateSubjectView, self).form_valid(form) + def get_object(self, queryset=None): context = get_object_or_404(Subject, slug = self.kwargs.get('slug')) return context @@ -769,7 +850,11 @@ class UpdateSubjectView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): context['subjects'] = self.object.course.subjects.all() return context -class DeleteSubjectView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): +class DeleteSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.DeleteView): + log_component = "course" + log_resource = "subject" + log_action = "delete" + log_context = {} allowed_roles = ['professor', 'system_admin'] login_url = reverse_lazy("core:home") @@ -783,7 +868,6 @@ class DeleteSubjectView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): return self.handle_no_permission() return super(DeleteSubjectView, self).dispatch(*args, **kwargs) - def get_context_data(self, **kwargs): context = super(DeleteSubjectView, self).get_context_data(**kwargs) context['course'] = self.object.course @@ -794,9 +878,21 @@ class DeleteSubjectView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): return context def get_success_url(self): + self.log_context['subject_id'] = self.object.id + self.log_context['subject_name'] = self.object.name + self.log_context['subject_slug'] = self.object.slug + self.log_context['course_id'] = self.object.course.id + self.log_context['course_name'] = self.object.course.name + self.log_context['course_slug'] = self.object.course.slug + self.log_context['course_category_id'] = self.object.course.category.id + self.log_context['course_category_name'] = self.object.course.category.name + + super(DeleteSubjectView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) + return reverse_lazy('course:view', kwargs={'slug' : self.object.course.slug}) @login_required +@log_decorator("course", "subscribe", "subject") def subscribe_subject(request, slug): subject = get_object_or_404(Subject, slug = slug) @@ -804,6 +900,18 @@ def subscribe_subject(request, slug): subject.students.add(request.user) if request.user in subject.students.all(): + log_context = {} + log_context['subject_id'] = subject.id + log_context['subject_name'] = subject.name + log_context['subject_slug'] = subject.slug + log_context['course_id'] = subject.course.id + log_context['course_name'] = subject.course.name + log_context['course_slug'] = subject.course.slug + log_context['course_category_id'] = subject.course.category.id + log_context['course_category_name'] = subject.course.category.name + + request.log_context = log_context + return JsonResponse({"status": "ok", "message": _("Successfully subscribed to the subject!")}) else: return JsonResponse({"status": "erro", "message": _("An error has occured. Could not subscribe to this subject, try again later")}) diff --git a/files/static/js/file.js b/files/static/js/file.js index 15d150b..ecb8f2d 100644 --- a/files/static/js/file.js +++ b/files/static/js/file.js @@ -1,7 +1,7 @@ function get_modal_file(url, id, div_content){ $.get(url, function (data) { - $(div_content).empty(); + $(div_content).detach(); $(div_content).append(data); $(id).modal('show'); }); diff --git a/forum/static/js/forum.js b/forum/static/js/forum.js index 622f8cb..43d958d 100644 --- a/forum/static/js/forum.js +++ b/forum/static/js/forum.js @@ -74,6 +74,8 @@ function setForumCreateFormSubmit(topic) { success: function (data) { $(".topic_" + topic).find('.foruns_list').append("
  • "+data.name+"
  • "); + alertify.success(data.message); + $("#createForum").modal('hide'); }, error: function(data) { @@ -221,6 +223,8 @@ function delete_post(url, post) { }, url: url, success: function(data) { + alertify.success(data); + $("#post_"+post).remove(); } }); diff --git a/forum/templates/forum/forum_form.html b/forum/templates/forum/forum_form.html index e11791f..0c3945e 100644 --- a/forum/templates/forum/forum_form.html +++ b/forum/templates/forum/forum_form.html @@ -15,21 +15,21 @@ {% render_field field %} {{ field.help_text }} - {% if field.errors %} -
    -
    - + {% endif %} + {% if field.errors %} +
    +
    + - {% endif %} +
    {% endif %}
    {% endfor %} diff --git a/forum/templates/post/post_render.html b/forum/templates/post/post_render.html index cf677ca..d6e21e7 100644 --- a/forum/templates/post/post_render.html +++ b/forum/templates/post/post_render.html @@ -8,7 +8,7 @@ {% trans 'reply' %} - {% if request.user|has_role:'system_admin' or request.user|has_role:'professor' and request.user == post.user %} + {% if request.user|has_role:'system_admin' or request.user == post.user %} {% csrf_token %}