Commit f9103c4b27ec969ea6f8d8753cd68fb281d66c3d

Authored by ailsoncgt
2 parents c9c4a9fb e4ae9d4b

Merge

Showing 44 changed files with 462 additions and 247 deletions   Show diff stats
amadeus/settings.py
... ... @@ -46,6 +46,7 @@ INSTALLED_APPS = [
46 46 'rest_framework',
47 47 'django_bootstrap_breadcrumbs',
48 48 's3direct',
  49 + 'django_summernote',
49 50  
50 51 'users',
51 52 'core',
... ... @@ -225,7 +226,59 @@ S3DIRECT_DESTINATIONS = {
225 226 # FILE UPLOAD
226 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 281 try:
229 282 from .local_settings import *
230 283 except ImportError:
231 284 - pass
  285 + pass
232 286 \ No newline at end of file
... ...
amadeus/urls.py
... ... @@ -28,6 +28,7 @@ urlpatterns = [
28 28  
29 29 #S3Direct
30 30 url(r'^s3direct/', include('s3direct.urls')),
  31 + url(r'^summernote/', include('django_summernote.urls')),
31 32 ]
32 33  
33 34 urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
... ...
app/views.py
... ... @@ -4,17 +4,14 @@ from django.views import View
4 4 from rolepermissions.mixins import HasRoleMixin
5 5 from django.contrib.auth.mixins import LoginRequiredMixin
6 6 from django.core.urlresolvers import reverse_lazy
7   -from core.mixins import LogMixin, NotificationMixin
  7 +from core.mixins import NotificationMixin
8 8 from core.models import Notification, Action, Resource, Action_Resource
9 9 from users.models import User
10 10 from .models import EmailBackend
11 11 from .forms import EmailBackendForm
12 12 from courses.models import Course
13 13  
14   -class AppIndex(LoginRequiredMixin, LogMixin, ListView, NotificationMixin):
15   - log_action = "Acessar"
16   - log_resource = "Home"
17   -
  14 +class AppIndex(LoginRequiredMixin, ListView, NotificationMixin):
18 15 login_url = reverse_lazy("core:home")
19 16 redirect_field_name = 'next'
20 17  
... ... @@ -46,7 +43,7 @@ class AppIndex(LoginRequiredMixin, LogMixin, ListView, NotificationMixin):
46 43  
47 44 return self.response_class(request = self.request, template = self.template_name, context = context, using = self.template_engine, **response_kwargs)
48 45  
49   -class AmadeusSettings(LoginRequiredMixin, HasRoleMixin, View):
  46 +class AmadeusSettings(LoginRequiredMixin, HasRoleMixin, View):
50 47 allowed_roles = ['system_admin']
51 48 login_url = reverse_lazy("core:home")
52 49 redirect_field_name = 'next'
... ...
core/decorators.py
1 1 from django.conf import settings
  2 +import json
2 3 from functools import wraps
3 4 from .models import Action, Resource, Action_Resource, Log, Notification
4 5  
5   -def log_decorator(log_action = '', log_resource = ''):
  6 +def log_decorator(log_component = '', log_action = '', log_resource = ''):
6 7  
7 8 def _log_decorator(view_function):
8 9  
... ... @@ -10,7 +11,7 @@ def log_decorator(log_action = &#39;&#39;, log_resource = &#39;&#39;):
10 11  
11 12 response = view_function(request, *args, **kwargs)
12 13  
13   - if request.user.is_authenticated and request.POST:
  14 + if request.user.is_authenticated:
14 15 action = Action.objects.filter(name = log_action)
15 16 resource = Resource.objects.filter(name = log_resource)
16 17  
... ... @@ -36,6 +37,8 @@ def log_decorator(log_action = &#39;&#39;, log_resource = &#39;&#39;):
36 37  
37 38 log = Log()
38 39 log.user = request.user
  40 + log.component = log_component
  41 + log.context = json.dumps(request.log_context)
39 42 log.action_resource = action_resource
40 43  
41 44 log.save()
... ...
core/migrations/0003_auto_20161101_1457.py 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-11-01 17:57
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.db import migrations, models
  6 +
  7 +
  8 +class Migration(migrations.Migration):
  9 +
  10 + dependencies = [
  11 + ('core', '0002_auto_20161024_1559'),
  12 + ]
  13 +
  14 + operations = [
  15 + migrations.AddField(
  16 + model_name='log',
  17 + name='component',
  18 + field=models.TextField(default='', verbose_name='Component (Module / App)'),
  19 + preserve_default=False,
  20 + ),
  21 + migrations.AddField(
  22 + model_name='log',
  23 + name='context',
  24 + field=models.TextField(blank=True, verbose_name='Context'),
  25 + ),
  26 + ]
... ...
core/mixins.py
1 1 from django.conf import settings
  2 +import json
  3 +
2 4 from .models import Action, Resource, Action_Resource, Log, Notification
3 5 from users.models import User
4 6  
5 7 class LogMixin(object):
  8 + log_component = ""
  9 + log_context = {}
6 10 log_action = ""
7 11 log_resource = ""
8 12  
9   - def dispatch(self, request, *args, **kwargs):
10   - action = Action.objects.filter(name = self.log_action)
11   - resource = Resource.objects.filter(name = self.log_resource)
  13 + def createLog(self, actor = None, component = '', log_action = '', log_resource = '', context = {}):
  14 + action = Action.objects.filter(name = log_action)
  15 + resource = Resource.objects.filter(name = log_resource)
12 16  
13 17 if not action:
14   - action = Action(name = self.log_action)
  18 + action = Action(name = log_action)
15 19 action.save()
16 20 else:
17 21 action = action[0]
18 22  
19 23 if not resource:
20   - resource = Resource(name = self.log_resource)
  24 + resource = Resource(name = log_resource)
21 25 resource.save()
22 26 else:
23 27 resource = resource[0]
... ... @@ -30,12 +34,18 @@ class LogMixin(object):
30 34 else:
31 35 action_resource = action_resource[0]
32 36  
  37 + print(context)
  38 + print(json.dumps(context))
  39 +
33 40 log = Log()
34   - log.user = request.user
  41 + log.user = actor
  42 + log.context = json.dumps(context)
  43 + log.component = component
35 44 log.action_resource = action_resource
36 45  
37 46 log.save()
38 47  
  48 + def dispatch(self, request, *args, **kwargs):
39 49 return super(LogMixin, self).dispatch(request, *args, **kwargs)
40 50  
41 51 class NotificationMixin(object):
... ...
core/models.py
... ... @@ -101,10 +101,15 @@ class Notification(models.Model):
101 101 return self.message
102 102  
103 103 class Log(models.Model):
104   - datetime = models.DateTimeField(_("Date and Time of action"), auto_now_add = True)
105   - user = models.ForeignKey(User, verbose_name = _('Actor'))
  104 + component = models.TextField(_('Component (Module / App)'))
  105 + context = models.TextField(_('Context'), blank = True)
106 106 action_resource = models.ForeignKey(Action_Resource, verbose_name = _('Action_Resource'))
  107 + user = models.ForeignKey(User, verbose_name = _('Actor'))
  108 + datetime = models.DateTimeField(_("Date and Time of action"), auto_now_add = True)
107 109  
108 110 class Meta:
109 111 verbose_name = _('Log')
110 112 verbose_name_plural = _('Logs')
  113 +
  114 + def __str__(self):
  115 + return self.context
... ...
core/static/css/base/amadeus.css
... ... @@ -420,7 +420,28 @@ ul, li {
420 420 .course, .subject, .topic{ padding-top: 0px; padding-bottom: 0px; }
421 421 .course-detail{padding-top: 10px; padding-bottom: 10px;}
422 422  
  423 +.course-card{
  424 + margin-bottom: 0.4% !important;
  425 +}
  426 +
  427 +.course-card-group{
  428 + margin-bottom: 1%;
  429 +}
  430 +
  431 +.category-course-link{
  432 + font-size: 24px;
  433 + color: black !important;
  434 +}
  435 +
423 436 /* Menu link remove radius */
424 437 .nav-pills > li > a {
425 438 border-radius: 0px;
426 439 }
  440 +
  441 +.float-button{
  442 + float: right;
  443 + position: fixed;
  444 + bottom: 5%;
  445 + right: 5%;
  446 + font-size: 20px;
  447 +}
... ...
core/templates/base.html
... ... @@ -20,7 +20,7 @@
20 20  
21 21 <!-- Bootstrap and themes (material) -->
22 22 <link rel="stylesheet" type="text/css" href="{% static 'bootstrap-3.3.7/css/bootstrap.css' %}">
23   -
  23 +
24 24 <link rel="stylesheet" type="text/css" href="{% static 'material/css/bootstrap-material-design.min.css' %}">
25 25 <link rel="stylesheet" type="text/css" href="{% static 'material/css/ripples.css' %}">
26 26 <link rel="stylesheet" type="text/css" href="{% static 'material/css/ripples.min.css' %}">
... ... @@ -79,7 +79,7 @@
79 79 <input type="text" class="form-control" placeholder="{% trans 'Search Files (.pdf, others) and/or activities' %}" name="search"></div>
80 80 <span class="input-group-btn input-group-sm">
81 81 <button type="submit" class="btn btn-fab btn-fab-mini">
82   - <i class="fa fa-search" aria-hidden="true"></i>
  82 + <i class="glyphicon glyphicon-search" aria-hidden="true" style="color:#93C741"></i>
83 83 </button>
84 84 </span>
85 85 </div>
... ...
core/templates/guest.html
... ... @@ -107,6 +107,7 @@
107 107 </div>
108 108 <div class="col-xs-10 col-sm-10 col-md-10 col-lg-10 col-xl-10">
109 109 {% block breadcrumbs %}
  110 +
110 111 <div class="col-md-12">
111 112 <form id="searchform" action="{% url 'course:manage' %}" method="get" accept-charset="utf-8">
112 113 <div class="input-group">
... ... @@ -121,46 +122,34 @@
121 122 </form>
122 123 </div>
123 124  
124   - <div class="col-md-10">
125   - <div class="btn-group btn-group-justified btn-group-raised">
126   - <a href="?category=all" class="btn btn-raised btn-info">{% trans 'All' %}</a>
127   - {% for category in categories %}
128   - <a href="?category={{category.name}}" class="btn btn-raised btn-primary">{{category.name}}</a>
129   - {% endfor %}
130   - </div>
131   - </div>
132   -
133 125 {% endblock %}
134 126 {% block render_breadcrumbs %}{% endblock %}
135 127 <div>
136 128 </div>
137 129 <div class="col-xs-12 col-sm-12 col-md-10 col-lg-10 col-xl-12">
138 130 {% block content %}
139   - {% for course in courses %}
140   - <div class="panel panel-info panel_{{ course.id }}">
141   - <div class="panel-heading">
142   - <a href="{{ course.get_absolute_url }}" class="panel-title">{{course.name}}</a>
143   - {% if user|show_course_subscribe:course %}
144   - <a onclick="subscribe($(this), '{% url 'course:subscribe' course.slug %}', {{ course.id}}, '{% trans 'Are you sure you want to subscribe to this course?' %}')" class="btn btn-sm btn-primary btn-raised pull-right" style="margin-top:-4px">{% trans 'Subscribe' %}</a>
145   - {% endif %}
146   - </div>
147   -
148   - <div class="panel-body">
149   - <p><b>{% trans 'Course Name' %}: </b>{{course.name}}</p>
150   - <p><b>{% trans 'Begining' %}: </b>{{course.init_date}}</p>
151   - <p><b>{% trans 'End' %}: </b>{{course.end_date}}</p>
152   - <p><b>{% trans 'Professor' %}: </b>{{course.professors.name}}</p>
153   - <p>
154   - <b>{% trans 'Description' %}:</b>
155   - <i>
156   - {{course.content}}
157   - </i>
158   - </p>
159   - </div>
160   - </div>
161   - {% endfor %}
162 131  
163   - {% pagination request paginator page_obj %}
  132 + <div class="col-md-12 cards-content">
  133 + {% for category in categorys_courses %}
  134 + <div class="panel-group">
  135 + <div class="panel panel-default">
  136 + <div class="panel-heading">
  137 + <h4 class="panel-title">
  138 + <a class="category-course-link" data-toggle="collapse" href="#{{category.slug}}">{{category.name}}</a>
  139 + </h4>
  140 +
  141 + </div>
  142 + <div id="{{category.slug}}" class="panel-collapse collapse">
  143 + {% for course in category.course_category.all %}
  144 + {%if course.public == True %}
  145 + {% include "course/course_card.html" %}
  146 + {% endif %}
  147 + {% endfor %}
  148 + </div>
  149 + </div>
  150 + </div>
  151 + {% endfor %}
  152 + </div>
164 153 {% endblock %}
165 154 </div>
166 155 </div>
... ...
core/views.py
... ... @@ -68,7 +68,6 @@ def remember_password(request):
68 68 context['danger'] = 'E-mail does not send'
69 69 return render(request, "remember_password.html",context)
70 70  
71   -@log_decorator('Acessar', 'Sistema')
72 71 def login(request):
73 72 context = {}
74 73  
... ... @@ -87,17 +86,12 @@ def login(request):
87 86  
88 87 return render(request,"index.html",context)
89 88  
90   -
91   -
92 89 def processNotification(self, notificationId):
93 90 notification = Notification.objects.get(id= notificationId)
94 91 notification.read = True
95 92 notification.save()
96 93 return redirect(notification.action_resource.resource.url)
97 94  
98   -
99   -
100   -
101 95 def getNotifications(request):
102 96 context = {}
103 97 if request.user.is_authenticated:
... ... @@ -133,5 +127,5 @@ class GuestView (ListView):
133 127  
134 128 def get_context_data (self, **kwargs):
135 129 context = super(GuestView, self).get_context_data(**kwargs)
136   - context['categories'] = CourseCategory.objects.all()
137   - return context
  130 + context['categorys_courses'] = CourseCategory.objects.all()
  131 + return context
138 132 \ No newline at end of file
... ...
courses/forms.py
... ... @@ -2,7 +2,7 @@ from django import forms
2 2 from django.utils.translation import ugettext_lazy as _
3 3 from .models import CourseCategory, Course, Subject, Topic, ActivityFile, Activity, FileMaterial, LinkMaterial
4 4 from s3direct.widgets import S3DirectWidget
5   -
  5 +from django_summernote.widgets import SummernoteWidget
6 6  
7 7 class CategoryCourseForm(forms.ModelForm):
8 8  
... ... @@ -19,24 +19,24 @@ class CategoryCourseForm(forms.ModelForm):
19 19  
20 20 class CourseForm(forms.ModelForm):
21 21 def clean_end_register_date(self):
22   - init_register_date = self.data['init_register_date']
23   - end_register_date = self.data['end_register_date']
  22 + init_register_date = self.cleaned_data['init_register_date']
  23 + end_register_date = self.cleaned_data['end_register_date']
24 24  
25 25 if init_register_date and end_register_date and end_register_date < init_register_date:
26 26 raise forms.ValidationError(_('The end date may not be before the start date.'))
27 27 return end_register_date
28 28  
29 29 def clean_init_date(self):
30   - end_register_date = self.data['end_register_date']
31   - init_date = self.data['init_date']
  30 + end_register_date = self.cleaned_data['end_register_date']
  31 + init_date = self.cleaned_data['init_date']
32 32  
33 33 if end_register_date and init_date and init_date <= end_register_date:
34 34 raise forms.ValidationError(_('The course start date must be after the end of registration.'))
35 35 return init_date
36 36  
37 37 def clean_end_date(self):
38   - init_date = self.data['init_date']
39   - end_date = self.data['end_date']
  38 + init_date = self.cleaned_data['init_date']
  39 + end_date = self.cleaned_data['end_date']
40 40  
41 41 if init_date and end_date and end_date < init_date:
42 42 raise forms.ValidationError(_('The end date may not be before the start date.'))
... ... @@ -79,8 +79,8 @@ class CourseForm(forms.ModelForm):
79 79  
80 80 widgets = {
81 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 86 class UpdateCourseForm(CourseForm):
... ... @@ -120,8 +120,8 @@ class UpdateCourseForm(CourseForm):
120 120 }
121 121 widgets = {
122 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 127 class SubjectForm(forms.ModelForm):
... ... @@ -143,6 +143,9 @@ class SubjectForm(forms.ModelForm):
143 143 'end_date': _('End date of the subject'),
144 144 'visible': _('Is the subject visible?'),
145 145 }
  146 + widgets = {
  147 + 'description':SummernoteWidget(),
  148 + }
146 149  
147 150 class TopicForm(forms.ModelForm):
148 151  
... ... @@ -157,6 +160,9 @@ class TopicForm(forms.ModelForm):
157 160 'name': _("Topic's name"),
158 161 'description': _("Topic's description"),
159 162 }
  163 + widgets = {
  164 + 'description':SummernoteWidget(),
  165 + }
160 166  
161 167 class ActivityFileForm(forms.ModelForm):
162 168 name = forms.CharField(
... ...
courses/static/js/topic_editation_presentation.js
... ... @@ -5,7 +5,8 @@ function show_editation(id_topic){
5 5 $(".presentation_"+ id_topic).css('display','none');
6 6 $(".editation_"+ id_topic).css('display','block');
7 7 };
8   - function show_presentation(id_topic){
  8 +
  9 +function show_presentation(id_topic){
9 10 $(".editation_"+ id_topic).css('display','none');
10 11 $(".presentation_"+ id_topic).css('display','block');
11 12 };
... ...
courses/templates/category/create.html
... ... @@ -31,13 +31,12 @@
31 31 </div>
32 32 <div class="panel-body">
33 33 <ul class="nav nav-pills nav-stacked">
34   - <li><a href="javascript:void(0)">{% trans 'Replicate Course' %}</a></li>
35 34 <li><a href="{% url 'course:create' %}">{% trans 'Create Course' %}</a></li>
36   - <li><a href="{% url 'course:create_cat' %}">{% trans 'Create Category' %}</a></li>
37 35 </ul>
38 36 </div>
39 37 </div>
40 38  
  39 +
41 40 <div class="panel panel-primary navigation">
42 41 <div class="panel-heading">
43 42 <h3 class="panel-title">{% trans 'Category' %}</h3>
... ...
courses/templates/category/delete.html
1   -{% load static i18n permission_tags %}
2 1  
3   -<!-- Modal (remember to change the ids!!!) -->
4   -<div class="modal fade" id="category" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
5   - <div class="modal-dialog" role="document">
6   - <div class="modal-content">
7   - <!-- Modal Header -->
8   - <div class="modal-header">
  2 +{% extends 'course/view.html' %}
9 3  
10   - <h4 class="modal-title" id="myModalLabel">{% trans "Delete Category" %}</h4>
11   - </div>
12   - <!-- Modal Body -->
13   - <div class="modal-body">
14   - <!-- Put ONLY your content here!!! -->
15   - <form id="delete_form" action="" method="post">
16   - {% csrf_token %}
17   - <p>{% trans 'Are you sure you want to delete the subject' %} "{{category.name}}"?</p>
18   - </form>
19   - </div>
20   - <!-- Modal Footer -->
21   - <div class="modal-footer">
22   - <!-- Don't remove that!!! -->
23   - <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
24   - <button type="submit" id="button" form="delete_form" class="btn btn-primary btn-raised">{% trans "Delete" %}</button>
25   - <script>
26   - $("#delete_form").submit(function(event) {
27   - Submite.remove("{% url 'course:delete_cat' category.slug %}",$(this).serialize(),"#category_{{category.slug}}");
28   - event.preventDefault();
29   - });
30   - </script>
31   - </div>
32   - </div>
  4 +{% load static i18n %}
  5 +
  6 +{% block breadcrumbs %}
  7 + <ol class="breadcrumb">
  8 + <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li>
  9 + <li><a href="{% url 'course:view' course.slug %}">{{ course }}</a></li>
  10 + </ol>
  11 +{% endblock %}
  12 +
  13 +{% block content %}
  14 +<div class="panel panel-default">
  15 + <div class="panel-body">
  16 + <form action="" method="post">
  17 + {% csrf_token %}
  18 + <h2>{% trans 'Are you sure you want to delete the course' %} "{{course}}"?</h2>
  19 + <input type="submit" class="btn btn-raised btn-success btn-lg" value="{% trans 'Yes' %}" />
  20 + <a href="{% url 'course:view' course.slug%}" class="btn btn-raised btn-danger btn-lg">{% trans 'No' %}</a>
  21 + </form>
33 22 </div>
34 23 </div>
35   -<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
36   -<script src="{% static 'js/modal_category.js' %}"></script>
  24 +{% endblock %}
37 25 \ No newline at end of file
... ...
courses/templates/category/index.html
... ... @@ -32,9 +32,7 @@
32 32 </div>
33 33 <div class="panel-body">
34 34 <ul class="nav nav-pills nav-stacked">
35   - <li><a href="javascript:void(0)">{% trans 'Replicate Course' %}</a></li>
36   - <li><a href="{% url 'course:creates' %}">{% trans 'Create Course' %}</a></li>
37   - <li><a href="{% url 'course:create_cat' %}">{% trans 'Create Category' %}</a></li>
  35 + <li><a href="{% url 'course:create' %}">{% trans 'Create Course' %}</a></li>
38 36 </ul>
39 37 </div>
40 38 </div>
... ... @@ -71,16 +69,15 @@
71 69 <div class="panel panel-info">
72 70 <div class="panel-heading" role="tab">
73 71 <div class="row">
74   - <div class="col-xs-9 col-md-10 titleTopic">
  72 + <div class="col-xs-9 col-md-11 titleTopic">
75 73 <h4 style="color:white; margin-left: 20px;">{{category}}</h4>
76 74 </div>
77   -
78   - <div class="col-xs-4 col-md-2" id="divMoreActions">
  75 + <div class="col-xs-4 col-md-1" id="divMoreActions">
79 76 <div class="btn-group">
80 77 <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
81 78 <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
82 79 </button>
83   - <ul class="dropdown-menu" aria-labelledby="moreActions">
  80 + <ul class="dropdown-menu pull-right" aria-labelledby="moreActions">
84 81 <li><a href="{% url 'course:update_cat' category.slug %}"><i class="fa fa-files-o fa-fw" aria-hidden="true"></i>{% trans 'Update' %}</a></li>
85 82 <li><a href="javascript:modal.get('{% url 'course:delete_cat' category.slug %}','#category','#modal_category');"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>{% trans 'Remover' %}</a></li>
86 83 </ul>
... ...
courses/templates/category/update.html
... ... @@ -32,9 +32,7 @@
32 32 </div>
33 33 <div class="panel-body">
34 34 <ul class="nav nav-pills nav-stacked">
35   - <li><a href="javascript:void(0)">{% trans 'Replicate Course' %}</a></li>
36 35 <li><a href="{% url 'course:create' %}">{% trans 'Create Course' %}</a></li>
37   - <li><a href="{% url 'course:create_cat' %}">{% trans 'Create Category' %}</a></li>
38 36 </ul>
39 37 </div>
40 38 </div>
... ...
courses/templates/course/course_card.html
1 1 {% load static i18n permission_tags %}
2 2 {% load django_bootstrap_breadcrumbs %}
3   -<div class="group">
  3 +<div class="group course-card ">
4 4 <div class="panel panel-info">
5 5 <div class="panel-heading course">
6 6 <div class="row">
... ... @@ -38,7 +38,7 @@
38 38 <p>
39 39 <b>{% trans 'Description' %}:</b>
40 40 <i>
41   - {{course.content}}
  41 + {{course.content | safe }}
42 42 </i>
43 43 </p>
44 44 </div>
... ...
courses/templates/course/create.html
1   -{% extends 'course/view.html' %}
  1 +{% extends 'home.html' %}
2 2  
3 3 {% load static i18n %}
4 4 {% load widget_tweaks %}
... ... @@ -19,7 +19,7 @@
19 19 <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput">
20 20 <label for="{{ field.auto_id }}">{{ field.label }}</label>
21 21 {% if field.auto_id == 'id_init_register_date' or field.auto_id == 'id_end_register_date' or field.auto_id == 'id_init_date' or field.auto_id == 'id_end_date'%}
22   - <input type="text" class="form-control date-picker" name="{{field.name}}" value="{{field.value|date:'SHORT_DATE_FORMAT'}}" min="{{now|date:'Y-m-d'}}">
  22 + <input type="text" class="form-control date-picker" name="{{field.name}}" value="{{field.value|date:'SHORT_DATE_FORMAT'}}" min="{{now|date:'SHORT_DATE_FORMAT'}}">
23 23 {% elif field.auto_id == 'id_image' %}
24 24 {% render_field field class='form-control' %}
25 25 <div class="input-group">
... ...
courses/templates/course/delete.html
1   -{% extends 'course/view.html' %}
  1 +{% load static i18n permission_tags %}
2 2  
3   -{% load static i18n %}
  3 +<!-- Modal (remember to change the ids!!!) -->
  4 +<div class="modal fade" id="course" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  5 + <div class="modal-dialog" role="document">
  6 + <div class="modal-content">
  7 + <!-- Modal Header -->
  8 + <div class="modal-header">
4 9  
5   -{% block breadcrumbs %}
6   - <ol class="breadcrumb">
7   - <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li>
8   - <li><a href="{% url 'course:view' course.slug %}">{{ course }}</a></li>
9   - </ol>
10   -{% endblock %}
11   -
12   -{% block content %}
13   -<div class="panel panel-default">
14   - <div class="panel-body">
15   - <form action="" method="post">
16   - {% csrf_token %}
17   - <h2>{% trans 'Are you sure you want to delete the course' %} "{{course}}"?</h2>
18   - <input type="submit" class="btn btn-raised btn-success btn-lg" value="{% trans 'Yes' %}" />
19   - <a href="{% url 'course:view' course.slug%}" class="btn btn-raised btn-danger btn-lg">{% trans 'No' %}</a>
  10 + <h4 class="modal-title" id="myModalLabel">{% trans "Delete Course" %}</h4>
  11 + </div>
  12 + <!-- Modal Body -->
  13 + <div class="modal-body">
  14 + <!-- Put ONLY your content here!!! -->
  15 + <form id="delete_form" action="" method="post">
  16 + {% csrf_token %}
  17 + <p>{% trans 'Are you sure you want to delete the course' %} "{{course.name}}"?</p>
20 18 </form>
21   - </div>
  19 + </div>
  20 + <!-- Modal Footer -->
  21 + <div class="modal-footer">
  22 + <!-- Don't remove that!!! -->
  23 + <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  24 + <button type="submit" id="button" form="delete_form" class="btn btn-primary btn-raised">{% trans "Delete" %}</button>
  25 + <script>
  26 + $("#delete_form").submit(function(event) {
  27 + RemoverCurso.remove("{% url 'course:delete' course.slug %}",$(this).serialize(),"#course_{{course.slug}}");
  28 + event.preventDefault();
  29 + });
  30 + </script>
  31 + </div>
  32 + </div>
  33 + </div>
22 34 </div>
23   -{% endblock %}
  35 +<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  36 +<script src="{% static 'js/course.js' %}"></script>
... ...
courses/templates/course/index.html
... ... @@ -42,7 +42,6 @@
42 42 </ul>
43 43 </div>
44 44 </div>
45   -
46 45 {% if user|has_role:'professor' or user|has_role:'system_admin' %}
47 46 <div class="panel panel-primary">
48 47 <div class="panel-heading">
... ... @@ -110,21 +109,34 @@
110 109  
111 110 </fieldset>
112 111 <div class="col-md-12 cards-content">
113   - {% if courses|length > 0 %}
114   - {% if request.GET.category == '' or aparece or request.GET.q == '' %}
115   - {% for course in list_courses %}
116   - {% include "course/course_card.html" %}
117   - {% endfor %}
118   - {% endif %}
119   - {% if request.GET.category or request.GET.q %}
120   - {% for course in courses %}
121   - {% include "course/course_card.html" %}
122   - {% endfor %}
123   - {% endif %}
124   - {% else %}
125   - {% trans 'No courses found' %}
126   - {% endif %}
  112 + {% for category in categorys_courses %}
  113 + <div class="panel-group course-card-group">
  114 + <div class="panel panel-default">
  115 + <div class="panel-heading">
  116 + <div class="row">
  117 + <div class="col-md-12">
  118 + <h4 class="panel-title">
  119 + <a class="category-course-link" data-toggle="collapse" href="#{{category.slug}}">{{category.name}}</a>
  120 + </h4>
  121 + </div>
  122 + </div>
  123 + </div>
  124 + <div id="{{category.slug}}" class="panel-collapse collapse">
  125 + {% for course in category.course_category.all %}
  126 + {% if user in course.students.all or user in course.professors.all or user|has_role:'system_admin' %}
  127 + {% include "course/course_card.html" %}
  128 + {% endif %}
  129 + {% endfor %}
  130 + </div>
  131 + </div>
  132 + </div>
  133 +
  134 +
  135 + {% endfor %}
127 136 </div>
  137 + {% if user|has_role:'professor' or user|has_role:'system_admin' %}
  138 + <a href="{% url 'course:create' %}" class="btn btn-primary btn-fab float-button"><i class="fa fa-plus material-icons"></i></a>
  139 + {% endif %}
128 140 <div class="col-md-12">
129 141 <nav aria-label="Page navigation">
130 142 <ul class="pagination">
... ... @@ -145,6 +157,7 @@
145 157 {% endif %}
146 158 </ul>
147 159 </nav>
  160 + <div class="row" id="modal_course">
148 161 </div>
149 162 <script type="text/javascript" src="{% static 'js/course.js' %}"></script>
150 163 {% endblock %}
... ...
courses/templates/course/replicate.html
... ... @@ -57,7 +57,7 @@
57 57 <label for="id_init_register_date">{% trans 'Course registration start date' %}</label>
58 58  
59 59  
60   - <input type="date" class="form-control" name="init_register_date" value="None" min="2016-10-24">
  60 + <input type="text" class="form-control date-picker" name="init_register_date" value="{{field.value|date:'SHORT_DATE_FORMAT'}}" min="{{now|date:'SHORT_DATE_FORMAT'}}">
61 61  
62 62 <span class="help-block">{% trans 'Date that starts the registration period of the course (dd/mm/yyyy)' %}</span>
63 63  
... ... @@ -67,7 +67,7 @@
67 67 <label for="id_end_register_date">{% trans 'Course registration end date' %}</label>
68 68  
69 69  
70   - <input type="date" class="form-control" name="end_register_date" value="None" min="2016-10-24">
  70 + <input type="text" class="form-control date-picker" name="end_register_date" value="{{field.value|date:'SHORT_DATE_FORMAT'}}" min="{{now|date:'SHORT_DATE_FORMAT'}}">
71 71  
72 72 <span class="help-block">{% trans 'Date that ends the registration period of the course (dd/mm/yyyy)' %}</span>
73 73  
... ... @@ -77,7 +77,7 @@
77 77 <label for="id_init_date">{% trans 'Course start date' %}</label>
78 78  
79 79  
80   - <input type="date" class="form-control" name="init_date" value="None" min="2016-10-24">
  80 + <input type="text" class="form-control date-picker" name="init_date" value="{{field.value|date:'SHORT_DATE_FORMAT'}}" min="{{now|date:'SHORT_DATE_FORMAT'}}">
81 81  
82 82 <span class="help-block">{% trans 'Date that the course starts (dd/mm/yyyy)' %}</span>
83 83  
... ... @@ -87,7 +87,7 @@
87 87 <label for="id_end_date">{% trans 'Course end date' %}</label>
88 88  
89 89  
90   - <input type="date" class="form-control" name="end_date" value="None" min="2016-10-24">
  90 + <input type="text" class="form-control date-picker" name="end_date" value="{{field.value|date:'SHORT_DATE_FORMAT'}}" min="{{now|date:'SHORT_DATE_FORMAT'}}">
91 91  
92 92 <span class="help-block">{% trans 'Date that the course ends (dd/mm/yyyy)' %}</span>
93 93  
... ...
courses/templates/course/view.html
... ... @@ -29,7 +29,24 @@
29 29 <li><a href="{% url 'core:home' %}">{% trans "Home" %}</a></li>
30 30 <li><a href="{% url 'users:profile' %}">{% trans 'Profile' %}</a></li>
31 31 <li><a href="{% url 'course:manage' %}">{% trans 'My Courses' %}</a></li>
32   - <li><a href="{% url 'core:guest' %}">{% trans 'All Courses' %}</a></li>
  32 + <li><a href="{% url 'course:all_courses' %}">{% trans 'All Courses' %}</a></li>
  33 + <li><a href="{% url 'core:guest' %}">{% trans 'Courses' %}</a></li>
  34 + {# <li><a href="{% url 'course:participants' %}">{% trans 'Participants' %}</a></li> #}
  35 + {% if user|has_role:'system_admin' %}
  36 + <li> <a href="{% url 'users:manage' %}">{% trans 'Manage Users' %}</a></li>
  37 + {% endif %}
  38 + {% if user|has_role:'system_admin' or user|has_role:'professor' %}
  39 + <li>
  40 + <a href="#courses_list" class="accordion" data-toggle="collapse">{% trans 'Manage Courses' %}</a>
  41 + <div id="courses_list" class="collapse">
  42 + <ul class="nav nav-pill nav-stacked accordion_list">
  43 + {% for course in courses_list %}
  44 + <li><a href="{% url 'course:view' course.slug %}">{{ course }}</a></li>
  45 + {% endfor %}
  46 + </ul>
  47 + </div>
  48 + </li>
  49 + {% endif %}
33 50 </ul>
34 51 </div>
35 52 </div>
... ... @@ -55,20 +72,19 @@
55 72 <div class="panel panel-info">
56 73 <div class="panel-heading course-detail">
57 74 <div class="row">
58   - <div class="col-xs-8 col-md-4 .titleTopic-detail">
  75 + <div class="col-xs-8 col-md-11 .titleTopic-detail">
59 76 <h4>{{course.name}}</h4>
60 77 </div>
61   - {% if user|has_role:'professor' and user in course.professors or user|has_role:'system_admin' %}
62   - <div class="col-xs-4 col-md-8" id="divMoreActions">
  78 + {% if user|has_role:'professor' or user|has_role:'system_admin' %}
  79 + <div class="col-xs-4 col-md-1" id="divMoreActions">
63 80 <div class="btn-group">
64 81 <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
65 82 <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
66 83 <div class="ripple-container"></div></button>
67   - <ul class="dropdown-menu" aria-labelledby="moreActions">
68   - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#createSubject"><i class="fa fa-plus-square-o" aria-hidden="true"></i>&nbsp; {% trans "Create Subject" %}</a></li>
69   - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal4"><i class="fa fa-files-o fa-fw" aria-hidden="true"></i>&nbsp; {% trans "Replicate" %}</a></li>
  84 + <ul class="dropdown-menu pull-right" aria-labelledby="moreActions">
  85 + <li><a href="{% url 'course:replicate_course' course.slug %}"><i class="fa fa-files-o fa-fw" aria-hidden="true"></i>&nbsp; {% trans "Replicate" %}</a></li>
70 86 <li><a href="{% url 'course:update' course.slug %}"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i>&nbsp; {% trans "Edit" %}</a></li>
71   - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal2"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp; {% trans "Remove" %}</a></li>
  87 + <li><a href="javascript:javascript:delete_course('{% url 'course:delete' course.slug %}', '{{ course.slug }}', '{% trans "Are you sure you want to delete this course?" %}', '{% url 'course:manage' %}')" data-toggle="modal" data-target="#myModal2"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp; {% trans "Remove" %}</a></li>
72 88 </ul>
73 89 </div>
74 90 </div>
... ... @@ -81,7 +97,7 @@
81 97 <p>
82 98 <b>{% trans 'Description' %}:</b>
83 99 <i>
84   - {{ course.objectivies }}
  100 + {{ course.objectivies |safe }}
85 101 </i>
86 102 </p>
87 103  
... ... @@ -142,20 +158,20 @@
142 158 <div class="col-md-1 moreAccordion" data-toggle="collapse" data-parent="#accordion-{{subject.slug}}" href=".collapseSubject-{{subject.slug}}" aria-expanded="false" aria-controls="collapseSubject-{{subject.slug}}">
143 159 <button class="btn btn-default btn-sm caret-square"><i class="fa fa-caret-square-o-down fa-2x" aria-hidden="true"></i></button>
144 160 </div>
145   - <div class="col-xs-9 col-md-4 titleTopic">
  161 + <div class="col-xs-9 col-md-10 titleTopic">
146 162 <a role="button" href="{% url 'course:view_subject' subject.slug %}">
147 163 <h4>{{subject.name}}</h4>
148 164 </a>
149 165 </div>
150   - {% if user|has_role:'professor' and user in subject.professors or user|has_role:'system_admin' %}
151   - <div class="col-xs-3 col-md-6" id="divMoreActions">
  166 + {% if user|has_role:'professor' or user|has_role:'system_admin' %}
  167 + <div class="col-xs-3 col-md-1" id="divMoreActions">
152 168 <div class="btn-group">
153 169 <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
154 170 <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
155 171 </button>
156   - <ul class="dropdown-menu" aria-labelledby="moreActions">
  172 + <ul class="dropdown-menu pull-right" aria-labelledby="moreActions">
157 173 <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal3"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i>&nbsp; {% trans 'Replicate' %}</a></li>
158   - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeSubject2"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp; {% trans 'Remove' %}</a></li>
  174 + <li><a href="javascript:subject.get('{% url 'course:delete_subject' subject.slug %}','#subject','#modal_subject');" data-toggle="modal" data-target="#removeSubject"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp; {% trans 'Remove' %}</a></li>
159 175 </ul>
160 176 </div>
161 177 </div>
... ... @@ -178,7 +194,7 @@
178 194 <p>
179 195 <b>{% trans "Description" %}: </b>
180 196 <i>
181   - {{subject.description}}
  197 + {{subject.description | safe}}
182 198 </i>
183 199 </p>
184 200 <div class="row">
... ... @@ -202,27 +218,6 @@
202 218 </div>
203 219 {% endif %}
204 220  
205   -<!-- MODAL REMOVE -->
206   - <div class="modal" id="removeSubject2">
207   - <div class="modal-dialog">
208   - <div class="modal-content">
209   - <div class="modal-header">
210   - <button type="button" class="close" data-dismiss="modal" aria-hidden="true">X</button>
211   - <h4 class="modal-title"></h4>
212   - </div>
213   - <div class="modal-body">
214   - <p> {% trans "Are you sure you want to remove this subject?" %}</p>
215   - </div>
216   - <div class="modal-footer">
217   -
218   - <a href="http://127.0.0.1:8080/html/screens/users/teacher/home_course_teacher.html" target="_self"><button type="button" class="btn btn-primary">{% trans "Confirm" %}</button></a>
219   -
220   - </div>
221   - </div>
222   - </div>
223   - </div>
224   -
225   -
226 221 </div>
227 222 </div>
228 223 </div>
... ...
courses/templates/subject/form_view_student.html
... ... @@ -27,7 +27,7 @@
27 27 <div class="presentation">
28 28 <p>
29 29 <i>
30   - {{topic.description|linebreaks}}
  30 + {{topic.description|safe}}
31 31 </i>
32 32 </p>
33 33  
... ...
courses/templates/subject/form_view_teacher.html
... ... @@ -19,11 +19,6 @@
19 19 </div><!--column -->
20 20 <div class="col-xs-3 col-md-2 divMoreActions">
21 21 <div class="btn-group">
22   - <button type="button" class="btn btn-default btn-sm eye" data-toggle="tooltip" data-placement="bottom" title="Visible">
23   - <i class="fa fa-eye fa-2x" aria-hidden="true"></i>
24   - </button>
25   - </div>
26   - <div class="btn-group">
27 22 <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
28 23 <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
29 24 </button>
... ... @@ -44,7 +39,7 @@
44 39 <div class="presentation_{{topic.slug}}">
45 40 <p>
46 41 <i>
47   - {{topic.description|linebreaks}}
  42 + {{topic.description|safe}}
48 43 </i>
49 44 </p>
50 45 </div>
... ...
courses/templates/subject/index.html
... ... @@ -23,6 +23,7 @@
23 23 <li><a href="{% url 'course:manage' %}">{% trans 'My courses' %}</a></li>
24 24 <li><a href="{% url 'core:guest' %}">{% trans 'All Courses' %}</a></li>
25 25 {% endif %}
  26 + <li><a href="{% url 'core:guest' %}">{% trans 'Courses' %}</a></li>
26 27 {% if user|has_role:'system_admin' %}
27 28 <li> <a href="{% url 'users:manage' %}">{% trans 'Manage Users' %}</a></li>
28 29 {% endif %}
... ... @@ -74,7 +75,7 @@
74 75 {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}</p>
75 76 <p>
76 77 <b>{% trans "Description" %}:</b>
77   - {{subject.description|linebreaks}}
  78 + {{subject.description|safe}}
78 79 </p>
79 80 <div class="row">
80 81 <div class="col-xs-6 col-md-6">
... ...
courses/templates/subject_category/index.html
... ... @@ -58,7 +58,7 @@
58 58 </div>
59 59 <div class="panel-body">
60 60 <p>
61   - {{subject.description|linebreaks}}
  61 + {{subject.description| safe }}
62 62 </p>
63 63 </div>
64 64 </div>
... ...
courses/templates/topic/index.html
... ... @@ -77,7 +77,7 @@
77 77 </div>
78 78 <div class="panel-body">
79 79 <p>
80   - {{topic.description|linebreaks}}
  80 + {{topic.description|safe}}
81 81 </p>
82 82 </div>
83 83 </div>
... ...
courses/views.py
... ... @@ -15,7 +15,8 @@ from rolepermissions.verifications import has_object_permission
15 15 from django.http import HttpResponseRedirect, JsonResponse
16 16 from .forms import CourseForm, UpdateCourseForm, CategoryCourseForm, SubjectForm,TopicForm,ActivityForm
17 17 from .models import Course, Subject, CourseCategory,Topic, SubjectCategory,Activity, CategorySubject
18   -from core.mixins import NotificationMixin
  18 +from core.decorators import log_decorator
  19 +from core.mixins import LogMixin, NotificationMixin
19 20 from users.models import User
20 21 from files.forms import FileForm
21 22 from files.models import TopicFile
... ... @@ -123,8 +124,8 @@ class AllCoursesView(LoginRequiredMixin, NotificationMixin, generic.ListView):
123 124 list_courses = None
124 125 categorys_courses = None
125 126 list_courses = Course.objects.all().order_by('name')
126   - categorys_courses = CourseCategory.objects.all().distinct().order_by('name')
127   -
  127 + #categorys_courses = CourseCategory.objects.all().distinct().order_by('name')
  128 + categorys_courses = CourseCategory.objects.all()
128 129 paginator = Paginator(list_courses, self.paginate_by)
129 130 page = self.request.GET.get('page')
130 131  
... ... @@ -141,7 +142,11 @@ class AllCoursesView(LoginRequiredMixin, NotificationMixin, generic.ListView):
141 142  
142 143 return context
143 144  
144   -class CreateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edit.CreateView):
  145 +class CreateCourseView(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin, generic.edit.CreateView):
  146 + log_component = "course"
  147 + log_resource = "course"
  148 + log_action = "create"
  149 + log_context = {}
145 150  
146 151 allowed_roles = ['professor', 'system_admin']
147 152 login_url = reverse_lazy("core:home")
... ... @@ -153,6 +158,15 @@ class CreateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,gener
153 158 def form_valid(self, form):
154 159 self.object = form.save()
155 160 self.object.professors.add(self.request.user)
  161 +
  162 + self.log_context['course_id'] = self.object.id
  163 + self.log_context['course_name'] = self.object.name
  164 + self.log_context['course_slug'] = self.object.slug
  165 + self.log_context['course_category_id'] = self.object.category.id
  166 + self.log_context['course_category_name'] = self.object.category.name
  167 +
  168 + super(CreateCourseView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  169 +
156 170 return super(CreateCourseView, self).form_valid(form)
157 171  
158 172 def get_context_data(self, **kwargs):
... ... @@ -160,13 +174,17 @@ class CreateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,gener
160 174 if has_role(self.request.user,'system_admin'):
161 175 courses = Course.objects.all()
162 176 elif has_role(self.request.user,'professor'):
163   - courses = self.request.user.courses.all()
  177 + courses = self.request.user.courses_student.all()
164 178 context['courses'] = courses
165 179 context['title'] = _("Create Course")
166 180 context['now'] = date.today()
167 181 return context
168 182  
169   -class ReplicateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edit.CreateView):
  183 +class ReplicateCourseView(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin,generic.edit.CreateView):
  184 + log_component = "courses"
  185 + log_action = "replicate"
  186 + log_resource = "course"
  187 + log_context = {}
170 188  
171 189 allowed_roles = ['professor', 'system_admin']
172 190 login_url = reverse_lazy("core:home")
... ... @@ -188,6 +206,15 @@ class ReplicateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,ge
188 206 elif has_role(self.request.user,'professor'):
189 207 courses = self.request.user.courses_professors.all()
190 208 categorys_courses = CourseCategory.objects.all()
  209 +
  210 + self.log_context['course_id'] = course.id
  211 + self.log_context['course_name'] = course.name
  212 + self.log_context['course_slug'] = course.slug
  213 + self.log_context['course_category_id'] = course.category.id
  214 + self.log_context['course_category_name'] = course.category.name
  215 +
  216 + super(ReplicateCourseView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  217 +
191 218 context['courses'] = courses
192 219 context['course'] = course
193 220 context['categorys_courses'] = categorys_courses
... ... @@ -198,7 +225,11 @@ class ReplicateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,ge
198 225 def get_success_url(self):
199 226 return reverse_lazy('course:view', kwargs={'slug' : self.object.slug})
200 227  
201   -class UpdateCourseView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView):
  228 +class UpdateCourseView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.UpdateView):
  229 + log_component = "courses"
  230 + log_action = "update"
  231 + log_resource = "course"
  232 + log_context = {}
202 233  
203 234 allowed_roles = ['professor', 'system_admin']
204 235 login_url = reverse_lazy("core:home")
... ... @@ -213,6 +244,19 @@ class UpdateCourseView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView):
213 244 return self.handle_no_permission()
214 245 return super(UpdateCourseView, self).dispatch(*args, **kwargs)
215 246  
  247 + def form_valid(self, form):
  248 + self.object = form.save()
  249 +
  250 + self.log_context['course_id'] = self.object.id
  251 + self.log_context['course_name'] = self.object.name
  252 + self.log_context['course_slug'] = self.object.slug
  253 + self.log_context['course_category_id'] = self.object.category.id
  254 + self.log_context['course_category_name'] = self.object.category.name
  255 +
  256 + super(UpdateCourseView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  257 +
  258 + return super(UpdateCourseView, self).form_valid(form)
  259 +
216 260 def get_context_data(self, **kwargs):
217 261 context = super(UpdateCourseView, self).get_context_data(**kwargs)
218 262 course = get_object_or_404(Course, slug = self.kwargs.get('slug'))
... ... @@ -229,7 +273,11 @@ class UpdateCourseView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView):
229 273 def get_success_url(self):
230 274 return reverse_lazy('course:view', kwargs={'slug' : self.object.slug})
231 275  
232   -class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView):
  276 +class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, LogMixin, generic.DeleteView):
  277 + log_component = "courses"
  278 + log_action = "delete"
  279 + log_resource = "course"
  280 + log_context = {}
233 281  
234 282 allowed_roles = ['professor', 'system_admin']
235 283 login_url = reverse_lazy("core:home")
... ... @@ -242,6 +290,15 @@ class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView):
242 290 course = get_object_or_404(Course, slug = self.kwargs.get('slug'))
243 291 if(not has_object_permission('delete_course', self.request.user, course)):
244 292 return self.handle_no_permission()
  293 +
  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 +
245 302 return super(DeleteCourseView, self).dispatch(*args, **kwargs)
246 303  
247 304 def get_context_data(self, **kwargs):
... ... @@ -258,7 +315,11 @@ class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView):
258 315 return context
259 316  
260 317  
261   -class CourseView(NotificationMixin, generic.DetailView):
  318 +class CourseView(LogMixin, NotificationMixin, generic.DetailView):
  319 + log_component = "courses"
  320 + log_action = "viewed"
  321 + log_resource = "course"
  322 + log_context = {}
262 323  
263 324 login_url = reverse_lazy("core:home")
264 325 redirect_field_name = 'next'
... ... @@ -272,6 +333,14 @@ class CourseView(NotificationMixin, generic.DetailView):
272 333 context = super(CourseView, self).get_context_data(**kwargs)
273 334 course = get_object_or_404(Course, slug = self.kwargs.get('slug'))
274 335  
  336 + self.log_context['course_id'] = course.id
  337 + self.log_context['course_name'] = course.name
  338 + self.log_context['course_slug'] = course.slug
  339 + self.log_context['course_category_id'] = course.category.id
  340 + self.log_context['course_category_name'] = course.category.name
  341 +
  342 + super(CourseView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  343 +
275 344 category_sub = self.kwargs.get('category', None)
276 345  
277 346 if has_role(self.request.user,'system_admin'):
... ... @@ -329,12 +398,23 @@ class DeleteView(LoginRequiredMixin, HasRoleMixin, NotificationMixin, generic.De
329 398 return self.response_class(request=self.request, template=self.get_template_names(), context=context, using=self.template_engine)
330 399  
331 400 @login_required
  401 +@log_decorator("course", "subscribe", "course")
332 402 def subscribe_course(request, slug):
333 403 course = get_object_or_404(Course, slug = slug)
334 404  
335 405 course.students.add(request.user)
336 406  
337 407 if request.user in course.students.all():
  408 +
  409 + log_context = {}
  410 + log_context['course_id'] = course.id
  411 + log_context['course_name'] = course.name
  412 + log_context['course_slug'] = course.slug
  413 + log_context['course_category_id'] = course.category.id
  414 + log_context['course_category_name'] = course.category.name
  415 +
  416 + request.log_context = log_context
  417 +
338 418 return JsonResponse({"status": "ok", "message": _("Successfully subscribed to the course!")})
339 419 else:
340 420 return JsonResponse({"status": "erro", "message": _("An error has occured. Could not subscribe to this course, try again later")})
... ... @@ -436,7 +516,11 @@ class DeleteCatView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView):
436 516 messages.success(self.request, _('Category deleted successfully!'))
437 517 return reverse_lazy('course:manage_cat')
438 518  
439   -class SubjectsView(LoginRequiredMixin, generic.ListView):
  519 +class SubjectsView(LoginRequiredMixin, LogMixin, generic.ListView):
  520 + log_component = "course"
  521 + log_resource = "subject"
  522 + log_action = "viewed"
  523 + log_context = {}
440 524  
441 525 login_url = reverse_lazy("core:home")
442 526 redirect_field_name = 'next'
... ... @@ -450,6 +534,17 @@ class SubjectsView(LoginRequiredMixin, generic.ListView):
450 534 if(not has_object_permission('view_subject', self.request.user, subject)):
451 535 return self.handle_no_permission()
452 536  
  537 + self.log_context['subject_id'] = subject.id
  538 + self.log_context['subject_name'] = subject.name
  539 + self.log_context['subject_slug'] = subject.slug
  540 + self.log_context['course_id'] = subject.course.id
  541 + self.log_context['course_name'] = subject.course.name
  542 + self.log_context['course_slug'] = subject.course.slug
  543 + self.log_context['course_category_id'] = subject.course.category.id
  544 + self.log_context['course_category_name'] = subject.course.category.name
  545 +
  546 + super(SubjectsView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  547 +
453 548 return super(SubjectsView, self).dispatch(*args, **kwargs)
454 549  
455 550 def get_queryset(self):
... ... @@ -527,6 +622,8 @@ class TopicsView(LoginRequiredMixin, generic.ListView):
527 622 context['students_activit'] = students_activit
528 623 context['materials'] = materials
529 624 context['form'] = ActivityForm
  625 +
  626 +
530 627  
531 628 return context
532 629  
... ... @@ -594,7 +691,11 @@ class UpdateTopicView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView):
594 691 context['subjects'] = topic.subject.course.subjects.all()
595 692 return context
596 693  
597   -class CreateSubjectView(LoginRequiredMixin, HasRoleMixin, NotificationMixin, generic.edit.CreateView):
  694 +class CreateSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin, generic.edit.CreateView):
  695 + log_component = "course"
  696 + log_resource = "subject"
  697 + log_action = "create"
  698 + log_context = {}
598 699  
599 700 allowed_roles = ['professor', 'system_admin']
600 701 login_url = reverse_lazy("core:home")
... ... @@ -626,6 +727,17 @@ class CreateSubjectView(LoginRequiredMixin, HasRoleMixin, NotificationMixin, gen
626 727 resource_slug = self.object.slug, actor=self.request.user, users= self.object.course.students.all(),
627 728 resource_link = reverse('course:view_subject', args=[self.object.slug]))
628 729  
  730 + self.log_context['subject_id'] = self.object.id
  731 + self.log_context['subject_name'] = self.object.name
  732 + self.log_context['subject_slug'] = self.object.slug
  733 + self.log_context['course_id'] = course.id
  734 + self.log_context['course_name'] = course.name
  735 + self.log_context['course_slug'] = course.slug
  736 + self.log_context['course_category_id'] = course.category.id
  737 + self.log_context['course_category_name'] = course.category.name
  738 +
  739 + super(CreateSubjectView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  740 +
629 741 return super(CreateSubjectView, self).form_valid(form)
630 742  
631 743  
... ...
files/static/js/file.js
1 1 function get_modal_file(url, id, div_content){
2 2  
3 3 $.get(url, function (data) {
4   - $(div_content).empty();
  4 + $(div_content).detach();
5 5 $(div_content).append(data);
6 6 $(id).modal('show');
7 7 });
... ...
files/templates/files/create_file.html
... ... @@ -47,7 +47,7 @@
47 47 <span id="helpBlock" class="help-block">{{ field.help_text }}</span>
48 48 {% endif %}
49 49 </div>
50   -
  50 +
51 51 {% if field.errors %}
52 52 <div class="alert alert-danger alert-dismissible clearfix" role="alert">
53 53 <button type="button" class="close" data-dismiss="alert" aria-label="Close">
... ... @@ -71,7 +71,7 @@
71 71  
72 72 <div class="form-group">
73 73 <div class="col-md-12">
74   - <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  74 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
75 75 <button class="btn btn-raised btn-primary" type="submit">{% trans 'Submit' %}</button>
76 76 </div>
77 77 </div>
... ... @@ -85,7 +85,7 @@
85 85 </div>
86 86  
87 87 {% block script_file %}
88   -
  88 +
89 89 {# // <script src="{% static 'js/file.js' %}"></script> #}
90 90 <script type="text/javascript">
91 91 $("#form-file").submit(function(event) {
... ...
files/templates/files/delete_file.html
... ... @@ -31,7 +31,7 @@
31 31 </div>
32 32 <div class="form-group">
33 33 <div class="col-md-12">
34   - <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  34 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
35 35 <button class="btn btn-raised btn-primary" type="submit">{% trans 'Delete' %}</button>
36 36 </div>
37 37 </div>
... ... @@ -45,7 +45,7 @@
45 45 </div>
46 46  
47 47 {% block script_file %}
48   -
  48 +
49 49 {# // <script src="{% static 'js/file.js' %}"></script> #}
50 50 <script type="text/javascript">
51 51 $("#form-delete-file").submit(function(event) {
... ...
files/templates/files/update_file.html
... ... @@ -52,7 +52,7 @@
52 52 <span id="helpBlock" class="help-block">{{ field.help_text }}</span>
53 53 {% endif %}
54 54 </div>
55   -
  55 +
56 56 {% if field.errors %}
57 57 <div class="alert alert-danger alert-dismissible clearfix" role="alert">
58 58 <button type="button" class="close" data-dismiss="alert" aria-label="Close">
... ... @@ -76,7 +76,7 @@
76 76  
77 77 <div class="form-group">
78 78 <div class="col-md-12">
79   - <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  79 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
80 80 <button class="btn btn-raised btn-primary" type="submit">{% trans 'Submit' %}</button>
81 81 </div>
82 82 </div>
... ... @@ -90,7 +90,7 @@
90 90 </div>
91 91  
92 92 {% block script_file %}
93   -
  93 +
94 94 {# // <script src="{% static 'js/file.js' %}"></script> #}
95 95 <script type="text/javascript">
96 96 $("#form-update-file").submit(function(event) {
... ...
forum/templates/forum/forum_view.html
... ... @@ -17,7 +17,7 @@
17 17 {% else %}
18 18 <li class="active">{{ forum.name }}</li>
19 19 {% endif %}
20   -
  20 +
21 21 </ol>
22 22 {% endblock %}
23 23  
... ... @@ -33,7 +33,7 @@
33 33 </ul>
34 34 </div>
35 35 </div>
36   -
  36 +
37 37 {% if request.user|has_role:'system_admin' or request.user|has_role:'professor' and request.user in forum.topic.subject.professors.all %}
38 38 <div class="panel panel-primary navigation">
39 39 <div class="panel-heading">
... ... @@ -121,7 +121,7 @@
121 121 </section>
122 122 </div>
123 123 <div class="modal-footer">
124   - <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans 'Close' %}</button>
  124 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans 'Close' %}</button>
125 125 <button type="button" onclick="$('#forum_create').submit();" class="btn btn-primary btn-raised">{% trans 'Update' %}</button>
126 126 </div>
127 127 </div>
... ...
links/static/js/links.js
1 1 function get_modal_link(url, id,div_content){
2 2 $.get(url, function (data) {
3   - $(div_content).empty();
  3 + $(div_content).detach();
4 4 $(div_content).append(data);
5 5 $(id).modal('show');
6 6 });
... ...
links/static/links.js
... ... @@ -1,8 +0,0 @@
1   -function get_modal_link(url, id,div_content){
2   - $.get(url, function (data) {
3   - $(div_content).empty();
4   - $(div_content).append(data);
5   - $(id).modal('show');
6   - });
7   -
8   -}
links/templates/links/create_link.html
1 1 {% load widget_tweaks i18n %}
2   -
3 2 <!--MODAL CREATE LINK-->
4 3 <div class="modal fade" id="createLinksModal" tabindex="-1" role="dialog" aria-labelledby="createLink">
5 4 <div class="modal-dialog" role="document">
... ... @@ -33,7 +32,7 @@
33 32 </div>
34 33 {% endfor %}
35 34 <div class="form-group">
36   - <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Cancel" %}</button>
  35 + <button type="button" class="btn btn-raised btn-default " data-dismiss="modal">{% trans "Cancel" %}</button>
37 36 <button class="btn btn-raised btn-primary" type="submit">{% trans 'Submit' %}</button>
38 37 </div>
39 38 <!-- .end Card -->
... ...
links/templates/links/delete_link.html
... ... @@ -21,7 +21,7 @@
21 21 </div>
22 22 <div class="form-group">
23 23 <div class="col-md-12">
24   - <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  24 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
25 25 <button class="btn btn-raised btn-primary" type="submit">{% trans 'Delete' %}</button>
26 26 </div>
27 27 </div>
... ...
links/templates/links/update_link.html
... ... @@ -36,7 +36,7 @@
36 36 {% endif %}
37 37 {% endfor %}
38 38 <div class="form-group">
39   - <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Cancel" %}</button>
  39 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Cancel" %}</button>
40 40 <button class="btn btn-raised btn-primary" type="submit">{% trans 'Submit' %}</button>
41 41 </div>
42 42 <!-- .end Card -->
... ...
links/templates/links/view_link.html
... ... @@ -14,7 +14,7 @@
14 14 <div class="card-block">
15 15 <b class="card-title">{{link.name}}</b><p></p>
16 16 <p class="card-text"> </p><p>{{link.link_description}}</p>
17   - <a href="{{ link.link_url }}" class="btn btn-primary">{% trans 'Read more' %}</a>
  17 + <a href="{{ link.link_url }}" class="btn btn-raised btn-primary">{% trans 'Read more' %}</a>
18 18 </div>
19 19 </article>
20 20 <!-- .end Card -->
... ...
poll/templates/poll/create.html
... ... @@ -151,7 +151,7 @@
151 151 <div class="modal-footer">
152 152  
153 153 <!-- Don't remove that!!! -->
154   - <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  154 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
155 155 {% block button_save %}
156 156 <!-- Put curtom buttons here!!! -->
157 157 <button type="submite" id="button" form="form" class="btn btn-primary btn-raised">{% trans "Create" %}</button>
... ...
requirements.txt
  1 +beautifulsoup4==4.5.1
1 2 click==6.6
2 3 decorator==4.0.10
3 4 deps==0.1.0
... ... @@ -10,18 +11,22 @@ django-floppyforms==1.7.0
10 11 django-modalview==0.1.5
11 12 django-role-permissions==1.2.1
12 13 django-s3direct==0.4.2
  14 +django-summernote==0.8.6
13 15 django-widget-tweaks==1.4.1
  16 +django-wysiwyg==0.8.0
14 17 djangorestframework==3.4.6
15 18 gunicorn==19.6.0
  19 +itsdangerous==0.24
16 20 Jinja2==2.8
  21 +lxml==3.6.4
17 22 MarkupSafe==0.23
18 23 Pillow==3.3.1
19 24 psycopg2==2.6.2
20 25 pycpfcnpj==1.0.2
  26 +requests==2.11.1
21 27 six==1.10.0
  28 +slugify==0.0.1
22 29 validators==0.11.0
  30 +virtualenv==15.0.3
23 31 Werkzeug==0.11.11
24 32 whitenoise==3.2.2
25   -beautifulsoup4==4.5.1
26   -lxml==3.6.4
27   -requests==2.11.1
... ...
users/templates/users/create.html
... ... @@ -38,7 +38,7 @@
38 38 {% else %}
39 39 <label for="{{ field.auto_id }}">{{ field.label }}</label>
40 40 {% endif %}
41   - <input type="text" class="form-control input-sm date-picker" name="{{field.name}}" min="{{now|date:'d-m-Y'}}">
  41 + <input type="text" class="form-control input-sm date-picker" name="{{field.name}}" min="{{now|date:'SHORT_DATE_FORMAT'}}">
42 42  
43 43 {% elif field.auto_id == 'id_image' %}
44 44 {% if field.field.required %}
... ...
users/templates/users/profile.html
... ... @@ -45,9 +45,11 @@
45 45 <div class="row">
46 46 <div class="col-md-4">
47 47 {% if user.image %}
48   - <div style="background-image: url('{{ user.image.url }}'); background-size: 100% 100%; background-repeat: no-repeat; margin-left: 8em;" alt="photoUser" class="img-circle img-responsive img-list-user"></div>
  48 + <div style="width: 200px; overflow:hidden; margin-left: 8em;">
  49 + <img src="{{ user.image.url }}" class="img-circle img-responsive img-list-user" >
  50 + </div>
49 51 {% else %}
50   - {% if usser.gender == 'M' %}
  52 + {% if user.gender == 'M' %}
51 53 <img src="{% static 'img/male_avatar.png' %}" alt="Avatar" class="img-circle img-responsive img-list-user" style="margin-left: 8em;">
52 54 {% else %}
53 55 <img src="{% static 'img/female_avatar.png' %}" alt="Avatar" class="img-circle img-responsive img-list-user" style="margin-left: 8em;">
... ...