Commit 2c886a7e73484e4896856c8e59bcc09ae8ca4fe6

Authored by ailsoncgt
2 parents a972f8d4 f3811ccd

Merge

Showing 59 changed files with 1036 additions and 848 deletions   Show diff stats
amadeus/urls.py
... ... @@ -23,6 +23,7 @@ urlpatterns = [
23 23 url(r'^home/', include('app.urls', namespace = 'app')),
24 24 url(r'^courses/', include('courses.urls', namespace = 'course')),
25 25 url(r'^users/', include('users.urls', namespace = 'users')),
  26 + url(r'^exercise/', include('exercise.urls', namespace = 'exercise')),
26 27 url(r'^admin/', admin.site.urls),
27 28 url(r'^', include('core.urls', namespace = 'core')),
28 29 #API
... ...
app/migrations/0001_initial.py
1 1 # -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
3 3 from __future__ import unicode_literals
4 4  
5 5 from django.db import migrations, models
... ...
app/templates/home.html
... ... @@ -96,8 +96,26 @@
96 96  
97 97 {% endblock %}
98 98 {% if user|has_role:'system_admin' %}
99   - <li> <a href="{% url 'users:manage' %}">{% trans 'Manage Users' %}</a></li>
100   - <li> <a href="{% url 'app:settings' %}">{% trans 'Settings' %}</a></li>
  99 +
  100 + <li>
  101 + <a href="#menu_users" class="accordion" data-toggle="collapse">{% trans 'Users' %}<span class="pull-right glyphicon glyphicon-chevron-down"></span></a>
  102 + <div id="menu_users" class="collapse">
  103 + <ul class="nav nav-pill nav-stacked accordion_list">
  104 + <li> <a href="{% url 'users:manage' %}">{% trans 'Manage Users' %}</a></li>
  105 + <li> <a href="{% url 'users:create' %}">{% trans 'Create User' %}</a></li>
  106 + </ul>
  107 + </div>
  108 + </li>
  109 + <li>
  110 + <a href="#menu_settings" class="accordion" data-toggle="collapse">{% trans 'Settings' %}<span class="pull-right glyphicon glyphicon-chevron-down"></span></a>
  111 + <div id="menu_settings" class="collapse">
  112 + <ul class="nav nav-pill nav-stacked accordion_list">
  113 + <li> <a href="{% url 'app:settings' %}">{% trans "System" %}</a></li>
  114 + <li> <a href="{% url 'app:settings' %}">{% trans "Mail Sender" %}</a></li>
  115 + <li> <a href="{% url 'app:settings' %}">{% trans "Security" %}</a></li>
  116 + </ul>
  117 + </div>
  118 + </li>
101 119 {% endif %}
102 120 </ul>
103 121 </div>
... ...
core/locale/pt_BR/LC_MESSAGES/django.po
... ... @@ -8,7 +8,7 @@ msgid &quot;&quot;
8 8 msgstr ""
9 9 "Project-Id-Version: PACKAGE VERSION\n"
10 10 "Report-Msgid-Bugs-To: \n"
11   -"POT-Creation-Date: 2016-11-16 11:23-0300\n"
  11 +"POT-Creation-Date: 2016-11-19 10:24-0300\n"
12 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14 14 "Language-Team: LANGUAGE <LL@li.org>\n"
... ... @@ -23,10 +23,8 @@ msgid &quot;Password&quot;
23 23 msgstr "Senha"
24 24  
25 25 #: .\forms.py:13
26   -#, fuzzy
27   -#| msgid "Confirm password:"
28 26 msgid "Confirm Password"
29   -msgstr "Confirmação de senha:"
  27 +msgstr "Confirme a senha:"
30 28  
31 29 #: .\forms.py:27
32 30 msgid "There is already a registered User with this e-mail"
... ... @@ -40,7 +38,7 @@ msgstr &quot;Por favor, insira uma data válida&quot;
40 38 #, fuzzy
41 39 #| msgid "There is already a registeres User with this CPF"
42 40 msgid "There is already a registered User with this CPF"
43   -msgstr "Já existem usuários cadastrados com este CPF"
  41 +msgstr "Já existe usuário cadastrado com este CPF"
44 42  
45 43 #: .\forms.py:52
46 44 #, python-format
... ... @@ -138,7 +136,7 @@ msgstr &quot;Autor&quot;
138 136 msgid "Notification"
139 137 msgstr "Notificação"
140 138  
141   -#: .\models.py:99 .\templates\base.html:92 .\templates\guest.html:70
  139 +#: .\models.py:99 .\templates\base.html:92
142 140 msgid "Notifications"
143 141 msgstr "Notificações"
144 142  
... ... @@ -166,11 +164,11 @@ msgstr &quot;Logs&quot;
166 164 msgid "Search Files (.pdf, others) and/or activities"
167 165 msgstr "Pesquisar arquivos (.pdf, outros) e/ou atividades"
168 166  
169   -#: .\templates\base.html:98 .\templates\guest.html:77
  167 +#: .\templates\base.html:98
170 168 msgid "See More"
171 169 msgstr "Ver Mais"
172 170  
173   -#: .\templates\base.html:105 .\templates\guest.html:83
  171 +#: .\templates\base.html:105
174 172 msgid "messages"
175 173 msgstr "Mensagens"
176 174  
... ... @@ -196,14 +194,22 @@ msgstr &quot;Mudar senha&quot;
196 194 msgid "Remove account"
197 195 msgstr "Remover conta"
198 196  
199   -#: .\templates\guest.html:97
  197 +#: .\templates\guest.html:67 .\templates\index.html:67 .\views.py:115
  198 +msgid "Guest"
  199 +msgstr "Convidado"
  200 +
  201 +#: .\templates\guest.html:80
200 202 msgid "Menu"
201 203 msgstr "Menu"
202 204  
203   -#: .\templates\guest.html:101 .\templates\register_user.html:110
  205 +#: .\templates\guest.html:84 .\templates\register_user.html:110
204 206 msgid "Register"
205 207 msgstr "Cadastrar"
206 208  
  209 +#: .\templates\guest.html:98
  210 +msgid "Search Courses"
  211 +msgstr "Pesquisar Cursos"
  212 +
207 213 #: .\templates\index.html:37
208 214 msgid "Sign in with your account to continue"
209 215 msgstr "Faça login com sua conta para continuar"
... ... @@ -220,10 +226,6 @@ msgstr &quot;Lembrar E-mail&quot;
220 226 msgid "Log in"
221 227 msgstr "Acessar"
222 228  
223   -#: .\templates\index.html:67
224   -msgid "Guest"
225   -msgstr "Convidado"
226   -
227 229 #: .\templates\index.html:72
228 230 msgid "Forgot your password?"
229 231 msgstr "Esqueceu sua senha?"
... ... @@ -236,9 +238,11 @@ msgstr &quot;Cadastrar&quot;
236 238 msgid "User Register"
237 239 msgstr "Cadastro de usuário"
238 240  
  241 +#: .\templates\register_user.html:61
  242 +msgid "Choose your photo..."
  243 +msgstr ""
  244 +
239 245 #: .\templates\register_user.html:71
240   -#, fuzzy
241   -#| msgid "Chose your file ..."
242 246 msgid "Choose the file ..."
243 247 msgstr "Escolha o arquivo..."
244 248  
... ... @@ -249,7 +253,7 @@ msgstr &quot;Entrar&quot;
249 253  
250 254 #: .\templates\registration\passwor_reset_complete.html:19
251 255 msgid "Your password was reseted successful"
252   -msgstr ""
  256 +msgstr "Sua senha foi resetada com sucesso"
253 257  
254 258 #: .\templates\registration\passwor_reset_confirm.html:19
255 259 #: .\templates\registration\passwor_reset_done.html:18
... ... @@ -389,9 +393,6 @@ msgstr &quot;E-mail ou senha incorretos.&quot;
389 393 #~ msgid "Manage Users"
390 394 #~ msgstr "Gerenciar usuários"
391 395  
392   -#~ msgid "Manage Courses"
393   -#~ msgstr "Gerenciar cursos"
394   -
395 396 #~ msgid "Category"
396 397 #~ msgstr "Categoria"
397 398  
... ...
core/migrations/0001_initial.py
1 1 # -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
3 3 from __future__ import unicode_literals
4 4  
5 5 import autoslug.fields
... ...
core/migrations/0002_auto_20161116_1057.py
... ... @@ -1,50 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
3   -from __future__ import unicode_literals
4   -
5   -from django.conf import settings
6   -from django.db import migrations, models
7   -import django.db.models.deletion
8   -
9   -
10   -class Migration(migrations.Migration):
11   -
12   - initial = True
13   -
14   - dependencies = [
15   - ('core', '0001_initial'),
16   - migrations.swappable_dependency(settings.AUTH_USER_MODEL),
17   - ]
18   -
19   - operations = [
20   - migrations.AddField(
21   - model_name='notification',
22   - name='actor',
23   - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_Performer', to=settings.AUTH_USER_MODEL, verbose_name='Performer'),
24   - ),
25   - migrations.AddField(
26   - model_name='notification',
27   - name='user',
28   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notification_Actor', to=settings.AUTH_USER_MODEL, verbose_name='User'),
29   - ),
30   - migrations.AddField(
31   - model_name='log',
32   - name='action_resource',
33   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource'),
34   - ),
35   - migrations.AddField(
36   - model_name='log',
37   - name='user',
38   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Actor'),
39   - ),
40   - migrations.AddField(
41   - model_name='action_resource',
42   - name='action',
43   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action', verbose_name='Action_Applied'),
44   - ),
45   - migrations.AddField(
46   - model_name='action_resource',
47   - name='resource',
48   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Resource', verbose_name='Resource'),
49   - ),
50   - ]
core/migrations/0002_auto_20161117_0217.py 0 → 100644
... ... @@ -0,0 +1,50 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.conf import settings
  6 +from django.db import migrations, models
  7 +import django.db.models.deletion
  8 +
  9 +
  10 +class Migration(migrations.Migration):
  11 +
  12 + initial = True
  13 +
  14 + dependencies = [
  15 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  16 + ('core', '0001_initial'),
  17 + ]
  18 +
  19 + operations = [
  20 + migrations.AddField(
  21 + model_name='notification',
  22 + name='actor',
  23 + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_Performer', to=settings.AUTH_USER_MODEL, verbose_name='Performer'),
  24 + ),
  25 + migrations.AddField(
  26 + model_name='notification',
  27 + name='user',
  28 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notification_Actor', to=settings.AUTH_USER_MODEL, verbose_name='User'),
  29 + ),
  30 + migrations.AddField(
  31 + model_name='log',
  32 + name='action_resource',
  33 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource'),
  34 + ),
  35 + migrations.AddField(
  36 + model_name='log',
  37 + name='user',
  38 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Actor'),
  39 + ),
  40 + migrations.AddField(
  41 + model_name='action_resource',
  42 + name='action',
  43 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action', verbose_name='Action_Applied'),
  44 + ),
  45 + migrations.AddField(
  46 + model_name='action_resource',
  47 + name='resource',
  48 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Resource', verbose_name='Resource'),
  49 + ),
  50 + ]
... ...
core/templates/guest.html
... ... @@ -64,24 +64,7 @@
64 64 </div>
65 65 <div class="navbar-collapse collapse navbar-responsive-collapse">
66 66 <ul class="nav navbar-nav navbar-right notifications">
67   - <li class="" data-toggle="tooltip" data-placement="bottom" title data-original-title="notifications">
68   - <a class="dropdown-toggle" data-toggle="dropdown"> <span id="notification-count" class="badge notification-count">{{notifications.count}}</span><i class="fa fa-bell" aria-hidden="true"></i></a>
69   - <ul id="notification-dropdown" class="dropdown-menu">
70   - <li class="dropdown-header">{% trans 'Notifications' %}</li>
71   - {% include "notifications.html" %}
72   -
73   - <li>
74   - <a onclick="getNotifications(5)">
75   - <div id="notification-see-more" class="list-group-item">
76   - <div class="row-content">
77   - <p class="list-group-item-text">{% trans 'See More' %}</p>
78   - </div>
79   - </a>
80   - </li>
81   - </ul>
82   - </li>
83   - <li data-toggle="tooltip" data-placement="bottom" title data-original-title="{% trans 'messages' %}"> <a href="#"><i class="fa fa-comments" aria-hidden="true"></i></a> </li>
84   - <li > <a class="link" href="{% url 'app:index' %}">{{ user }}</a></li>
  67 + <li > <a class="link" href="{% url 'app:index' %}">{% trans 'Guest' %}</a></li>
85 68 <li data-toggle="tooltip" data-placement="bottom" title data-original-title="log out"> <a href="{% url 'app:index' %}"><i class="fa fa-sign-out" aria-hidden="true"></i></a></li>
86 69 </ul>
87 70 </div>
... ... @@ -107,21 +90,6 @@
107 90 </div>
108 91 <div class="col-xs-10 col-sm-10 col-md-10 col-lg-10 col-xl-10">
109 92 {% block breadcrumbs %}
110   -
111   - <div class="col-md-12">
112   - <form id="searchform" action="{% url 'course:manage' %}" method="get" accept-charset="utf-8">
113   - <div class="input-group">
114   - <div class="form-group is-empty">
115   - <input type="search" class="form-control" placeholder="Search Courses" name="q" id="searchbox"></div>
116   - <span class="input-group-btn input-group-sm">
117   - <button type="button" class="btn btn-fab btn-fab-mini">
118   - <i class="material-icons">search</i>
119   - </button>
120   - </span>
121   - </div>
122   - </form>
123   - </div>
124   -
125 93 {% endblock %}
126 94 {% block render_breadcrumbs %}{% endblock %}
127 95 <div>
... ... @@ -137,7 +105,7 @@
137 105 <h4 class="panel-title">
138 106 <a class="category-course-link" data-toggle="collapse" href="#{{category.slug}}">{{category.name}}</a>
139 107 </h4>
140   -
  108 +
141 109 </div>
142 110 <div id="{{category.slug}}" class="panel-collapse collapse">
143 111 {% for course in category.course_category.all %}
... ... @@ -150,6 +118,27 @@
150 118 </div>
151 119 {% endfor %}
152 120 </div>
  121 + <div class="col-md-12">
  122 + <nav aria-label="Page navigation">
  123 + <ul class="pagination">
  124 + {% if page_obj.has_previous %}
  125 + <li>
  126 + <a href="?page={{ page_obj.previous_page_number }}"><span><<</span></a>
  127 + </li>
  128 + {% endif %}
  129 + {% for page_number in paginator.page_range %}
  130 + <li{% if page_obj.number == page_number %} class="active"{% endif %}>
  131 + <a href="?page={{ page_number }}">{{ page_number }}</a>
  132 + </li>
  133 + {% endfor %}
  134 + {% if page_obj.has_next %}
  135 + <li>
  136 + <a href="?page={{ page_obj.next_page_number }}"><span>>></span></a>
  137 + </li>
  138 + {% endif %}
  139 + </ul>
  140 + </nav>
  141 + </div>
153 142 {% endblock %}
154 143 </div>
155 144 </div>
... ... @@ -161,4 +150,4 @@
161 150 {% endblock script_file %}
162 151 </body>
163 152  
164   -</html>
165 153 \ No newline at end of file
  154 +</html>
... ...
core/templates/register_user.html
... ... @@ -58,7 +58,7 @@
58 58 {% elif field.auto_id == 'id_image' %}
59 59 {% render_field field class='form-control' %}
60 60 <div class="input-group">
61   - <input type="text" readonly="" class="form-control" placeholder="Choose your photo...">
  61 + <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your photo...' %}">
62 62 <span class="input-group-btn input-group-sm">
63 63 <button type="button" class="btn btn-fab btn-fab-mini">
64 64 <i class="material-icons">image</i>
... ...
core/views.py
... ... @@ -14,6 +14,8 @@ from core.mixins import NotificationMixin
14 14 from .models import Notification, Log
15 15 from rolepermissions.shortcuts import assign_role
16 16 from django.contrib.auth.decorators import login_required
  17 +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
  18 +
17 19 #API REST IMPORTS
18 20 from .serializers import LogSerializer
19 21 from rest_framework import status, serializers, permissions, viewsets
... ... @@ -103,15 +105,24 @@ class GuestView (ListView):
103 105  
104 106 template_name = 'guest.html'
105 107 context_object_name = 'courses'
  108 + queryset = CourseCategory.objects.all()
106 109 paginate_by = 10
107 110  
108   - def get_queryset(self):
109   - return Course.objects.filter(public=True)
110   -
111   -
112 111 def get_context_data (self, **kwargs):
113 112 context = super(GuestView, self).get_context_data(**kwargs)
114   - context['categorys_courses'] = CourseCategory.objects.all()
  113 + context['title'] = _("Guest")
  114 + queryset_list = CourseCategory.objects.all()
  115 +
  116 + paginator = Paginator(queryset_list, 10)
  117 + page = self.request.GET.get('page')
  118 + try:
  119 + queryset_list = paginator.page(page)
  120 + except PageNotAnInteger:
  121 + queryset_list = paginator.page(1)
  122 + except EmptyPage:
  123 + queryset_list = paginator.page(paginator.num_pages)
  124 +
  125 + context['categorys_courses'] = queryset_list
115 126 return context
116 127  
117 128  
... ...
courses/migrations/0001_initial.py
1 1 # -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
3 3 from __future__ import unicode_literals
4 4  
5 5 import autoslug.fields
... ... @@ -69,8 +69,8 @@ class Migration(migrations.Migration):
69 69 ],
70 70 options={
71 71 'verbose_name_plural': 'Courses',
72   - 'ordering': ('create_date', 'name'),
73 72 'verbose_name': 'Course',
  73 + 'ordering': ('create_date', 'name'),
74 74 },
75 75 ),
76 76 migrations.CreateModel(
... ... @@ -128,8 +128,8 @@ class Migration(migrations.Migration):
128 128 ],
129 129 options={
130 130 'verbose_name_plural': 'Subjects',
131   - 'ordering': ('create_date', 'name'),
132 131 'verbose_name': 'Subject',
  132 + 'ordering': ('create_date', 'name'),
133 133 },
134 134 ),
135 135 migrations.CreateModel(
... ... @@ -160,8 +160,8 @@ class Migration(migrations.Migration):
160 160 ],
161 161 options={
162 162 'verbose_name_plural': 'Topics',
163   - 'ordering': ('create_date', 'name'),
164 163 'verbose_name': 'Topic',
  164 + 'ordering': ('create_date', 'name'),
165 165 },
166 166 ),
167 167 ]
... ...
courses/migrations/0002_auto_20161116_1057.py
... ... @@ -1,85 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
3   -from __future__ import unicode_literals
4   -
5   -from django.conf import settings
6   -from django.db import migrations, models
7   -import django.db.models.deletion
8   -
9   -
10   -class Migration(migrations.Migration):
11   -
12   - initial = True
13   -
14   - dependencies = [
15   - migrations.swappable_dependency(settings.AUTH_USER_MODEL),
16   - ('courses', '0001_initial'),
17   - ]
18   -
19   - operations = [
20   - migrations.AddField(
21   - model_name='subject',
22   - name='professors',
23   - field=models.ManyToManyField(related_name='professors_subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors'),
24   - ),
25   - migrations.AddField(
26   - model_name='subject',
27   - name='students',
28   - field=models.ManyToManyField(blank=True, related_name='subject_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'),
29   - ),
30   - migrations.AddField(
31   - model_name='material',
32   - name='students',
33   - field=models.ManyToManyField(related_name='materials', to=settings.AUTH_USER_MODEL, verbose_name='Students'),
34   - ),
35   - migrations.AddField(
36   - model_name='material',
37   - name='topic',
38   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='courses.Topic', verbose_name='Topic'),
39   - ),
40   - migrations.AddField(
41   - model_name='linkmaterial',
42   - name='material',
43   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_link', to='courses.Material', verbose_name='Material'),
44   - ),
45   - migrations.AddField(
46   - model_name='filematerial',
47   - name='material',
48   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_file', to='courses.Material', verbose_name='Material'),
49   - ),
50   - migrations.AddField(
51   - model_name='course',
52   - name='category',
53   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_category', to='courses.CourseCategory', verbose_name='Category'),
54   - ),
55   - migrations.AddField(
56   - model_name='course',
57   - name='coordenator',
58   - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='course_coordenator', to=settings.AUTH_USER_MODEL, verbose_name='Coordenator'),
59   - ),
60   - migrations.AddField(
61   - model_name='course',
62   - name='professors',
63   - field=models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors'),
64   - ),
65   - migrations.AddField(
66   - model_name='course',
67   - name='students',
68   - field=models.ManyToManyField(blank=True, related_name='courses_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'),
69   - ),
70   - migrations.AddField(
71   - model_name='activityfile',
72   - name='diet',
73   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='courses.Activity'),
74   - ),
75   - migrations.AddField(
76   - model_name='activity',
77   - name='students',
78   - field=models.ManyToManyField(related_name='activities', to=settings.AUTH_USER_MODEL, verbose_name='Students'),
79   - ),
80   - migrations.AddField(
81   - model_name='activity',
82   - name='topic',
83   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='courses.Topic', verbose_name='Topic'),
84   - ),
85   - ]
courses/migrations/0002_auto_20161117_0217.py 0 → 100644
... ... @@ -0,0 +1,85 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.conf import settings
  6 +from django.db import migrations, models
  7 +import django.db.models.deletion
  8 +
  9 +
  10 +class Migration(migrations.Migration):
  11 +
  12 + initial = True
  13 +
  14 + dependencies = [
  15 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  16 + ('courses', '0001_initial'),
  17 + ]
  18 +
  19 + operations = [
  20 + migrations.AddField(
  21 + model_name='subject',
  22 + name='professors',
  23 + field=models.ManyToManyField(related_name='professors_subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors'),
  24 + ),
  25 + migrations.AddField(
  26 + model_name='subject',
  27 + name='students',
  28 + field=models.ManyToManyField(blank=True, related_name='subject_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'),
  29 + ),
  30 + migrations.AddField(
  31 + model_name='material',
  32 + name='students',
  33 + field=models.ManyToManyField(related_name='materials', to=settings.AUTH_USER_MODEL, verbose_name='Students'),
  34 + ),
  35 + migrations.AddField(
  36 + model_name='material',
  37 + name='topic',
  38 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='courses.Topic', verbose_name='Topic'),
  39 + ),
  40 + migrations.AddField(
  41 + model_name='linkmaterial',
  42 + name='material',
  43 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_link', to='courses.Material', verbose_name='Material'),
  44 + ),
  45 + migrations.AddField(
  46 + model_name='filematerial',
  47 + name='material',
  48 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_file', to='courses.Material', verbose_name='Material'),
  49 + ),
  50 + migrations.AddField(
  51 + model_name='course',
  52 + name='category',
  53 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_category', to='courses.CourseCategory', verbose_name='Category'),
  54 + ),
  55 + migrations.AddField(
  56 + model_name='course',
  57 + name='coordenator',
  58 + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='course_coordenator', to=settings.AUTH_USER_MODEL, verbose_name='Coordenator'),
  59 + ),
  60 + migrations.AddField(
  61 + model_name='course',
  62 + name='professors',
  63 + field=models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors'),
  64 + ),
  65 + migrations.AddField(
  66 + model_name='course',
  67 + name='students',
  68 + field=models.ManyToManyField(blank=True, related_name='courses_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'),
  69 + ),
  70 + migrations.AddField(
  71 + model_name='activityfile',
  72 + name='diet',
  73 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='courses.Activity'),
  74 + ),
  75 + migrations.AddField(
  76 + model_name='activity',
  77 + name='students',
  78 + field=models.ManyToManyField(related_name='activities', to=settings.AUTH_USER_MODEL, verbose_name='Students'),
  79 + ),
  80 + migrations.AddField(
  81 + model_name='activity',
  82 + name='topic',
  83 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='courses.Topic', verbose_name='Topic'),
  84 + ),
  85 + ]
... ...
courses/templates/subject/form_view_student.html
... ... @@ -63,33 +63,6 @@
63 63 </ul>
64 64 </div>
65 65 </div>
66   - <div class="col-xs-4 col-md-4">
67   - <div class="resource_inline">
68   - <h4>{% trans 'Exercises' %}</h4>
69   - </div>
70   - <div class="resource_inline">
71   - {# dropdown de create exercício #}
72   - <div class="dropdown">
73   - <a href="#" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-plus-circle fa-lg" aria-hidden="true"></i></a>
74   - <ul class="dropdown-menu" aria-labelledby="dLabel">
75   - <li><a href="javascript:modal.get('{% url 'course:exercise:create_exercise' topic.slug %}', '#createExercisesModal','#requisicoes_ajax')">{% trans 'Create a Exercise' %}</a></li>
76   - </ul>
77   - </div>
78   - </div>
79   - <div class="presentation_{{exercise.slug}}">
80   - {# exercício do tópico no modo de visualização #}
81   - <ul>
82   - {% list_topic_exercise request %}
83   - </ul>
84   - </div>
85   - <div class="editation editation_{{exercise.slug}}">
86   - {# exercício do tópico no modo de edição #}
87   - <ul>
88   - {% list_topic_exercise_edit request exercise %}
89   - </ul>
90   - </div>
91   - </div>
92   - {% include "exercise/create_exercise.html" %}
93 66 </div>
94 67 {% endif %}
95 68  
... ...
courses/templates/subject/form_view_teacher.html
... ... @@ -7,7 +7,7 @@
7 7 <button class="btn btn-default btn-sm caret-square"><i class="fa fa-caret-square-o-down fa-2x" aria-hidden="true"></i></button>
8 8 </div>
9 9 <div class="col-xs-9 col-md-9 titleTopic">
10   - <a role="button">
  10 + <a href="{% url 'course:view_topic' topic.slug %}" role="button">
11 11 <h4>{{topic}}</h4>
12 12 </a>
13 13 </div><!--column -->
... ... @@ -21,7 +21,7 @@
21 21 {% professor_subject topic.subject user as dropdown_topic %}
22 22 {% if dropdown_topic %}
23 23 <ul class="dropdown-menu pull-right" aria-labelledby="moreActions">
24   - <li><a href="" data-toggle="modal" data-target="#myModal4"><i class="fa fa-files-o fa-fw" aria-hidden="true"></i>&nbsp; {% trans "Replicate" %}</a></li>
  24 + <li><a href="{% url 'course:replicate_topic' topic.slug %}"><i class="fa fa-files-o fa-fw" aria-hidden="true"></i>&nbsp; {% trans "Replicate" %}</a></li>
25 25 <li><a href="javascript:show_editation('{{topic.slug}}')"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i>&nbsp; {% trans "Edit" %}</a></li>
26 26 <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeTopic"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp; {% trans "Remove" %}</a></li>
27 27 </ul>
... ... @@ -123,23 +123,18 @@
123 123 </ul>
124 124 </div>
125 125 </div>
126   - <div class="col-xs-4 col-md-4">
127 126 <div class="resource_inline">
128 127 <h4>{% trans 'Exercises' %}</h4>
129 128 </div>
130   - <div class="presentation_{{exercise.slug}}">
131   - {# exercício do tópico no modo de visualização #}
132   - <ul>
133   - {% list_topic_exercise request %}
134   - </ul>
135   - </div>
136   - <div class="editation editation_{{exercise.slug}}">
137   - {# exercício do tópico no modo de edição #}
138   - <ul>
139   - {% list_topic_exercise_edit request exercise %}
140   - </ul>
  129 + <div class="resource_inline">
  130 + {# dropdown de create exercício #}
  131 + <div class="dropdown">
  132 + <a href="#" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-plus-circle fa-lg" aria-hidden="true"></i></a>
  133 + <ul class="dropdown-menu" aria-labelledby="dLabel">
  134 + <li><a href="javascript:modal.get('{% url 'course:exercise:create_exercise' topic.slug %}', '#createExercisesModal','#requisicoes_ajax')">{% trans 'Create a general exercise' %}</a></li>
  135 + </ul>
  136 + </div>
141 137 </div>
142   - </div>
143 138 </div>
144 139  
145 140 {# opções de cancelar e editar no modo de edição #}
... ...
courses/templates/subject/replicate.html
... ... @@ -2,61 +2,51 @@
2 2  
3 3 {% load static i18n permission_tags widget_tweaks %}
4 4  
5   -{% block breadcrumbs %}
6   - <ol class="breadcrumb">
7   - <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li>
8   - <li class="active">{% trans 'Replicate Subject' %}</li>
9   - </ol>
10   -{% endblock %}
11   -
12 5 {% block content %}
13   -<div class="panel panel-default">
  6 +
  7 + <div class="panel panel-default">
14 8 <div class="panel-body">
15 9 <form class="form-group " method="post" action="">
16 10 {% csrf_token %}
17 11  
18 12 <div class="form-group {% if subject.name.errors %} has-error{% endif %}">
19   - <label for="{{ id_name }}" class="control-label label-static"> {% trans 'Name' %}</label>
20   - <input class="form-control" id="id_name" maxlength="100" name="name" type="text" required="True" value="{{subject.name}}">
21   - <span class="help-block">{% trans 'Subject name' %}</span>
  13 + <label for="id_name" class="control-label label-static"> {% trans 'Name'%}</label>
  14 + <textarea class="form-control" id="id_name" maxlength="100" rows="1" name="name" placeholder="Name" type="text" required >{{subject.name}}</textarea>
22 15  
  16 + <span class="help-block">{% trans 'Subject name'%}</span>
23 17 </div>
24 18  
25   - <div class="form-group {% if subject.name.errors %} has-error{% endif %}">
26   - <label for="{{ id_description }}" class="control-label label-static"> {% trans 'Description' %} </label>
27   - <textarea class="form-control" id="id_description" name="description" type="text" required="">{{subject.description}}</textarea>
28   - <span class="help-block">{% trans 'Subject Description' %}</span>
  19 + <div class="form-group">
  20 + <label for="id_description" class="control-label label-static"> {% trans 'Description'%}</label>
  21 + <textarea class="form-control" id="id_description" name="description" placeholder="Description" type="text" >{{subject.description}}</textarea>
29 22  
  23 + <span class="help-block">{% trans 'Subject description'%}</span>
30 24 </div>
31 25  
32   - <div class="form-group {% if subject.name.errors %} has-error{% endif %}">
33   - <label for="{{ id_init_date }}" class="control-label label-static"> {% trans 'Init date' %}</label>
34   - <input type="text" class="form-control date-picker" name="{{field.name}}" value="{{field.value|date:'SHORT_DA E_FORMAT'}}" min="{{now|date:'SHORT_DATE_FORMAT'}}">
35   - <span class="help-block">{% trans 'Subject init date' %}</span>
  26 + <div class="form-group">
  27 + <label for="id_init_date" class="control-label label-static"> {% trans 'Init date'%}</label>
  28 + <input type="text" class="form-control date-picker" name="init_date" value="{{field.value|date:'SHORT_DATE_FORMAT'}}" min="{{now|date:'SHORT_DATE_FORMAT'}}">
36 29  
  30 + <span class="help-block">{% trans 'Init date'%}</span>
37 31 </div>
38 32  
39   - <div class="form-group {% if subject.name.errors %} has-error{% endif %}">
40   - <label for="{{ id_end_date }}" class="control-label label-static"> {% trans 'End date' %}</label>
41   - <input type="text" class="form-control date-picker" name="{{field.name}}" value="{{field.value|date:'SHORT_DA E_FORMAT'}}" min="{{now|date:'SHORT_DATE_FORMAT'}}">
42   - <span class="help-block">{% trans 'Subject end date' %}</span>
43   -
44   - </div>
45   - <div class="form-group {% if subject.name.errors %} has-error{% endif %}">
46   - <label for="{{ id_visible }}" class="control-label label-static"> {% trans 'Visible?' %} </label>
47   - <input type="checkbox" class="form-control" id="id_visible" name="visible" required="true"/>
48   - <span class="help-block">{% trans 'Is it visible?' %}</span>
  33 + <div class="form-group">
  34 + <label for="id_end_date" class="control-label label-static"> {% trans 'End date'%}</label>
  35 + <input type="text" class="form-control date-picker" name="end_date" value="{{field.value|date:'SHORT_DATE_FORMAT'}}" min="{{now|date:'SHORT_DATE_FORMAT'}}">
49 36  
  37 + <span class="help-block">{% trans 'End date'%}</span>
50 38 </div>
51 39  
  40 + <div class="form-group">
  41 + <label for="id_visible" class="control-label label-static"> {% trans 'Visible'%}</label>
  42 + <input class="form-control" id="id_visible" name="visible" type="checkbox"/>
52 43  
  44 + <span class="help-block">{% trans 'Is it visible?'%}</span>
53 45 </div>
54   -
55 46 <div class="col-lg-offset-4 col-lg-4">
56   - <button type="submit" class="btn btn-raised btn-primary btn-lg btn-block">{% trans 'Replicate' %}</button>
  47 + <button type="submite" class="btn btn-raised btn-primary btn-lg btn-block">{% trans 'Replicate' %}</button>
57 48 </div>
58 49 </form>
59   -
60 50 </div>
61 51 </div>
62 52  
... ... @@ -70,4 +60,4 @@
70 60 $('#id_description').summernote({height: 300});
71 61 });
72 62 </script>
73   -{% endblock %}
74 63 \ No newline at end of file
  64 +{% endblock content %}
... ...
courses/templates/topic/index.html
... ... @@ -65,7 +65,7 @@
65 65 </div>
66 66 <div class="panel panel-default">
67 67 <div class="panel-body">
68   - {% include "topic/topic_card_student.html" %}
  68 + {% include "topic/topic_card.html" %}
69 69 {% comment %}
70 70  
71 71  
... ... @@ -116,13 +116,23 @@
116 116 </fieldset>
117 117 </form>-->
118 118 {% endcomment %}
119   -
120   -
121   -
122   -
123 119 </div>
124   -
125   -
126 120 </div>
127 121 </div>
  122 + <div class="col-md-6">
  123 + <h3>{% trans 'Students - Specific Exercises' %}</h3>
  124 + <br/>
  125 + </div>
  126 + {# mostra a lista de usuários caso seja um professor ou admin #}
  127 + {% if user|has_role:'professor' or user|has_role:'system_admin' %}
  128 + {% for user in users %}
  129 + {% include "exercise/card_list_user.html" %}
  130 + {% endfor %}
  131 + {% endif %}
  132 + {# caso seja um estudante, mostra a lista de exercícios proposta a ele #}
  133 + {% if user|has_role:'student'%}
  134 + {% for exercise in exercises %}
  135 + {% include "exercise/card_topic_exercises.html" %}
  136 + {% endfor %}
  137 + {% endif %}
128 138 {% endblock %}
... ...
courses/templates/topic/replicate.html 0 → 100644
... ... @@ -0,0 +1,38 @@
  1 +{% extends 'subject/index.html' %}
  2 +
  3 +{% load static i18n permission_tags widget_tweaks %}
  4 +
  5 +{% block content %}
  6 +
  7 + <div class="panel panel-default">
  8 + <div class="panel-body">
  9 + <form class="form-group " method="post" action="">
  10 + {% csrf_token %}
  11 +
  12 + <div class="form-group {% if topic.name.errors %} has-error{% endif %}">
  13 + <label for="id_name" class="control-label label-static"> {% trans 'Name'%}</label>
  14 + <textarea class="form-control" id="id_name" maxlength="100" rows="1" name="name" placeholder="Name" type="text" required >{{topic.name}}</textarea>
  15 +
  16 + <span class="help-block">{% trans 'Topic name'%}</span>
  17 + </div>
  18 + <div class="form-group {% if topic.description.errors %} has-error{% endif %}">
  19 + <label for="id_description" class="control-label label-static"> {% trans 'Description'%}</label>
  20 + <textarea class="form-control" id="id_description" name="description" placeholder="Description" type="text"> {{topic.description}}</textarea>
  21 +
  22 + <span class="help-block">{% trans 'Topic description'%}</span>
  23 + </div>
  24 +
  25 + <div class="col-lg-offset-4 col-lg-4">
  26 + <button type="submit" class="btn btn-raised btn-primary btn-lg btn-block">{% trans 'Create' %}</button>
  27 +
  28 + </div>
  29 + </form>
  30 + </div>
  31 + </div>
  32 +
  33 + <script type="text/javascript">
  34 + $(document).ready(function() {
  35 + $('#id_description').summernote({height: 300});
  36 + });
  37 + </script>
  38 +{% endblock content %}
... ...
courses/templates/topic/replicate_topic.html
... ... @@ -1,38 +0,0 @@
1   -{% extends 'subject/index.html' %}
2   -
3   -{% load static i18n permission_tags widget_tweaks %}
4   -
5   -{% block content %}
6   -
7   - <div class="panel panel-default">
8   - <div class="panel-body">
9   - <form class="form-group " method="post" action="">
10   - {% csrf_token %}
11   -
12   - <div class="form-group {% if topic.name.errors %} has-error{% endif %}">
13   - <label for="id_name" class="control-label label-static"> {% trans 'Name'%}</label>
14   - <input class="form-control" id="id_name" maxlength="100" name="name" placeholder="Name" type="text" value={{topic.name}} required />
15   -
16   - <span class="help-block">{% trans 'Topic name'%}</span>
17   - </div>
18   - <div class="form-group {% if topic.description.errors %} has-error{% endif %}">
19   - <label for="id_description" class="control-label label-static"> {% trans 'Description'%}</label>
20   - <textarea class="form-control" id="id_description" name="description" placeholder="Description" type="text"> {{topic.description}}</textarea>
21   -
22   - <span class="help-block">{% trans 'Topic description'%}</span>
23   - </div>
24   -
25   - <div class="col-lg-offset-4 col-lg-4">
26   - <button type="submit" class="btn btn-raised btn-primary btn-lg btn-block">{% trans 'Create' %}</button>
27   -
28   - </div>
29   - </form>
30   - </div>
31   - </div>
32   -
33   - <script type="text/javascript">
34   - $(document).ready(function() {
35   - $('#id_description').summernote({height: 300});
36   - });
37   - </script>
38   -{% endblock content %}
courses/templates/topic/topic_card.html 0 → 100644
... ... @@ -0,0 +1,28 @@
  1 +{% load static i18n list_topic_foruns permission_tags widget_tweaks professor_access%}
  2 +
  3 +
  4 +<div class="row">
  5 + <div class="col-xs-6 col-md-6">
  6 + <div class="resource_inline">
  7 + <h4>{% trans "Materials" %}</h4>
  8 + </div>
  9 +
  10 + <ul id="list-materials">
  11 + {% list_topic_file request topic %}
  12 + {% list_topic_link request topic%}
  13 +
  14 + </ul>
  15 + </div>
  16 + <div class="col-xs-6 col-md-6">
  17 + <div class="resource_inline">
  18 + <h4>{% trans "Activities" %}</h4>
  19 + </div>
  20 + <ul>
  21 + <div class="foruns_list">
  22 + {# {% list_topic_exam request topic %} #}
  23 + {% list_topic_poll request topic %}
  24 + {% list_topic_foruns request topic %}
  25 + </div>
  26 + </ul>
  27 + </div>
  28 +</div>
0 29 \ No newline at end of file
... ...
courses/templates/topic/topic_card_student.html
... ... @@ -1,29 +0,0 @@
1   -{% load static i18n list_topic_foruns permission_tags widget_tweaks professor_access%}
2   -
3   -
4   -<div class="row">
5   - <div class="col-xs-6 col-md-6">
6   - <div class="resource_inline">
7   - <h4>{% trans "Materials" %}</h4>
8   - </div>
9   -
10   - <ul id="list-materials">
11   - {% list_topic_file request topic %}
12   - {% list_topic_link request topic%}
13   -
14   - </ul>
15   - </div>
16   - <div class="col-xs-4 col-md-4">
17   - <div class="resource_inline">
18   - <h4>{% trans "Activities" %}</h4>
19   - </div>
20   - <ul>
21   - <div class="foruns_list">
22   - {% list_topic_exam request topic %}
23   - {% list_topic_poll request topic %}
24   - {% list_topic_foruns request topic %}
25   - </div>
26   - </ul>
27   - </div>
28   -
29   -</div>
courses/urls.py
... ... @@ -6,7 +6,6 @@ urlpatterns = [
6 6 url(r'^all-courses/$', views.AllCoursesView.as_view(), name='all_courses'),
7 7 url(r'^create/$', views.CreateCourseView.as_view(), name='create'),
8 8 url(r'^replicate_course/(?P<slug>[\w_-]+)/$', views.ReplicateCourseView.as_view(), name='replicate_course'),
9   - url(r'^replicate_subject/(?P<slug>[\w_-]+)/$', views.ReplicateSubjectView.as_view(), name='replicate_subject'),
10 9 url(r'^edit/(?P<slug>[\w_-]+)/$', views.UpdateCourseView.as_view(), name='update'),
11 10 url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteCourseView.as_view(), name='delete'),
12 11 url(r'^subscribe/(?P<slug>[\w_-]+)/$', views.subscribe_course, name='subscribe'),
... ... @@ -19,10 +18,11 @@ urlpatterns = [
19 18 url(r'^subjects/create/(?P<slug>[\w_-]+)/$', views.CreateSubjectView.as_view(), name='create_subject'),
20 19 url(r'^subjects/update/(?P<slug>[\w_-]+)/$', views.UpdateSubjectView.as_view(), name='update_subject'),
21 20 url(r'^subjects/delete/(?P<slug>[\w_-]+)/$', views.DeleteSubjectView.as_view(), name='delete_subject'),
  21 + url(r'^subjects/replicate/(?P<slug>[\w_-]+)/$', views.ReplicateSubjectView.as_view(), name='replicate_subject'),
22 22 url(r'^subjects/subscribe/(?P<slug>[\w_-]+)/$', views.subscribe_subject, name='subscribe_subject'),
23 23 url(r'^topics/create/(?P<slug>[\w_-]+)/$', views.CreateTopicView.as_view(), name='create_topic'),
24 24 url(r'^topics/update/(?P<slug>[\w_-]+)/$', views.UpdateTopicView.as_view(), name='update_topic'),
25   - url(r'^topics/update/(?P<slug>[\w_-]+)/$', views.DeleteTopic.as_view(), name='delete_topic'),
  25 + url(r'^topics/delete/(?P<slug>[\w_-]+)/$', views.DeleteTopic.as_view(), name='delete_topic'),
26 26 url(r'^topics/replicate/(?P<slug>[\w_-]+)/$', views.ReplicateTopicView.as_view(), name='replicate_topic'),
27 27 url(r'^topics/(?P<slug>[\w_-]+)/$', views.TopicsView.as_view(), name='view_topic'),
28 28 url(r'^subjects/categories$',views.IndexSubjectCategoryView.as_view(), name='subject_category_index'),
... ...
courses/views.py
... ... @@ -56,7 +56,7 @@ def course_category(list_courses):
56 56 if (cat):
57 57 categorys_courses.append(cat)
58 58  
59   - return categorys_courses
  59 + return sorted(list(categorys_courses),key = lambda x:x.name)
60 60  
61 61 class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView):
62 62  
... ... @@ -93,10 +93,10 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView):
93 93 list_courses = self.get_queryset().order_by('name')
94 94 # categorys_courses = CourseCategory.objects.all()
95 95 elif has_role(self.request.user,'professor'):
96   - list_courses = self.get_queryset().filter(professors__in = [self.request.user])
  96 + list_courses = self.get_queryset().filter(professors__in = [self.request.user]).order_by('name')
97 97 # categorys_courses = CourseCategory.objects.filter(course_category__professors__name = self.request.user.name).distinct()
98 98 elif has_role(self.request.user, 'student'):
99   - list_courses = self.get_queryset().filter(students__in = [self.request.user])
  99 + list_courses = self.get_queryset().filter(students__in = [self.request.user]).order_by('name')
100 100  
101 101 context['categorys_courses'] = course_category(list_courses)
102 102 return context
... ... @@ -136,6 +136,7 @@ class AllCoursesView(LoginRequiredMixin, NotificationMixin, generic.ListView):
136 136 list_courses = self.get_queryset()
137 137  
138 138 context['categorys_courses'] = course_category(list_courses)
  139 +
139 140 return context
140 141  
141 142 class CreateCourseView(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin, generic.edit.CreateView):
... ... @@ -561,39 +562,6 @@ class SubjectsView(LoginRequiredMixin, LogMixin, generic.ListView):
561 562 context['files'] = TopicFile.objects.filter(students__name = self.request.user.name)
562 563 return context
563 564  
564   -class ReplicateSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin,generic.edit.CreateView):
565   -
566   - allowed_roles = ['professor', 'system_admin']
567   - login_url = reverse_lazy("core:home")
568   - redirect_field_name = 'next'
569   - template_name = 'subject/replicate.html'
570   - form_class = SubjectForm
571   - success_url = reverse_lazy('course:view')
572   -
573   - def get_context_data(self, **kwargs):
574   - context = super(ReplicateSubjectView, self).get_context_data(**kwargs)
575   - subject = get_object_or_404(Subject, slug=self.kwargs.get('slug'))
576   -
577   - if has_role(self.request.user,'system_admin'):
578   - subjects = Subject.objects.all()
579   - context['subjects'] = subjects
580   - elif has_role(self.request.user,'professor'):
581   - subject = self.request.user.professors_subjects.all()
582   - categorys_subjects = CategorySubject.objects.all()
583   -
584   - context['subject'] = subject
585   - context['categorys_subjects'] = categorys_subjects
586   - context['title'] = _("Replicate Subject")
587   - context['now'] = date.today()
588   - return context
589   -
590   - def form_valid(self, form):
591   - self.object = form.save()
592   -
593   - return super(ReplicateSubjectView, self).form_valid(form)
594   -
595   - def get_success_url(self):
596   - return reverse_lazy('course:view', kwargs={'slug' : self.object.slug})
597 565  
598 566 class UploadMaterialView(LoginRequiredMixin, generic.edit.CreateView):
599 567 login_url = reverse_lazy("core:home")
... ... @@ -663,6 +631,11 @@ class TopicsView(LoginRequiredMixin, LogMixin, generic.ListView):
663 631 activitys = Activity.objects.filter(topic__name = topic.name)
664 632 students_activit = User.objects.filter(activities__in = Activity.objects.all())
665 633 materials = Material.objects.filter(topic = topic)
  634 +
  635 + users = User.objects.filter(subject_student__in = Subject.objects.all())
  636 + context['users'] = users
  637 + exercises = Exercise.objects.filter(Q(students=self.request.user)|Q(professors=self.request.user))
  638 + context['exercises'] = exercises
666 639  
667 640 context['topic'] = topic
668 641 context['subject'] = topic.subject
... ... @@ -1017,13 +990,13 @@ class TopicViewSet(viewsets.ModelViewSet):
1017 990 class ReplicateTopicView (LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin,generic.edit.CreateView):
1018 991 log_component = "course"
1019 992 log_resource = "topic"
1020   - log_action = "create"
  993 + log_action = "replicate"
1021 994 log_context = {}
1022 995  
1023 996 allowed_roles = ['professor', 'system_admin']
1024 997 login_url = reverse_lazy("core:home")
1025   - model = Topic
1026   - template_name = 'topic/replicate_topic.html'
  998 + redirect_field_name = 'next'
  999 + template_name = 'topic/replicate.html'
1027 1000 form_class = TopicForm
1028 1001  
1029 1002 def get_success_url(self):
... ... @@ -1032,21 +1005,23 @@ class ReplicateTopicView (LoginRequiredMixin, HasRoleMixin, LogMixin, Notificati
1032 1005 def get_context_data(self, **kwargs):
1033 1006 context = super(ReplicateTopicView, self).get_context_data(**kwargs)
1034 1007 topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
1035   - subject = topic.subject
  1008 + subject = Subject.objects.get(pk = topic.subject_id)
1036 1009 context['course'] = subject.course
1037 1010 context['subject'] = subject
1038 1011 context['subjects'] = subject.course.subjects.all()
1039 1012 context['topic'] = topic
1040 1013 return context
1041 1014  
1042   -
1043 1015 def form_valid(self, form):
1044   - self.object.subject = self.object.subject.id
  1016 + topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
  1017 + subject = Subject.objects.get(pk = topic.subject_id)
  1018 +
1045 1019 self.object = form.save(commit = False)
  1020 + self.object.topic = topic
  1021 + self.object.subject = subject
1046 1022 self.object.owner = self.request.user
1047 1023 self.object.save()
1048   -
1049   - action = super(ReplicateTopicView, self).createorRetrieveAction("replicate Topic")
  1024 + action = super(ReplicateTopicView, self).createorRetrieveAction("create Topic")
1050 1025 super(ReplicateTopicView, self).createNotification("Topic "+ self.object.name + " was created",
1051 1026 resource_name=self.object.name, resource_link= reverse('course:view_topic',args=[self.object.slug]),
1052 1027 actor=self.request.user, users = self.object.subject.course.students.all() )
... ... @@ -1066,3 +1041,55 @@ class ReplicateTopicView (LoginRequiredMixin, HasRoleMixin, LogMixin, Notificati
1066 1041 super(ReplicateTopicView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
1067 1042  
1068 1043 return super(ReplicateTopicView, self).form_valid(form)
  1044 +
  1045 +class ReplicateSubjectView(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin, generic.edit.CreateView):
  1046 + log_component = "course"
  1047 + log_resource = "subject"
  1048 + log_action = "replicate"
  1049 + log_context = {}
  1050 +
  1051 + allowed_roles = ['professor', 'system_admin']
  1052 + login_url = reverse_lazy("core:home")
  1053 + redirect_field_name = 'next'
  1054 + template_name = 'subject/replicate.html'
  1055 + form_class = SubjectForm
  1056 +
  1057 + def get_success_url(self):
  1058 + return reverse_lazy('course:view_subject', kwargs={'slug' : self.object.slug})
  1059 +
  1060 + def get_context_data(self, **kwargs):
  1061 + context = super(ReplicateSubjectView, self).get_context_data(**kwargs)
  1062 + subject = get_object_or_404(Subject, slug = self.kwargs.get('slug'))
  1063 + course = Course.objects.get(pk=subject.course_id)
  1064 + context['course'] = course
  1065 + context['subjects'] = course.subjects.filter(Q(visible=True) | Q(professors__in=[self.request.user]))
  1066 + context['subject'] = subject
  1067 + if (has_role(self.request.user,'system_admin')):
  1068 + context['subjects'] = course.subjects.all()
  1069 + return context
  1070 +
  1071 + def form_valid(self, form):
  1072 + subject = get_object_or_404(Subject, slug = self.kwargs.get('slug'))
  1073 + course = Course.objects.get(pk=subject.course_id)
  1074 +
  1075 + self.object = form.save(commit = False)
  1076 + self.object.course = course
  1077 + self.object.save()
  1078 + self.object.professors.add(self.request.user)
  1079 + if self.object.visible:
  1080 + super(ReplicateSubjectView, self).createNotification( " created subject " + self.object.name, resource_name=self.object.name,
  1081 + resource_slug = self.object.slug, actor=self.request.user, users= self.object.course.students.all(),
  1082 + resource_link = reverse('course:view_subject', args=[self.object.slug]))
  1083 +
  1084 + self.log_context['subject_id'] = self.object.id
  1085 + self.log_context['subject_name'] = self.object.name
  1086 + self.log_context['subject_slug'] = self.object.slug
  1087 + self.log_context['course_id'] = course.id
  1088 + self.log_context['course_name'] = course.name
  1089 + self.log_context['course_slug'] = course.slug
  1090 + self.log_context['course_category_id'] = course.category.id
  1091 + self.log_context['course_category_name'] = course.category.name
  1092 +
  1093 + super(ReplicateSubjectView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  1094 +
  1095 + return super(ReplicateSubjectView, self).form_valid(form)
... ...
exam/migrations/0001_initial.py
1 1 # -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
3 3 from __future__ import unicode_literals
4 4  
5 5 from django.db import migrations, models
... ... @@ -24,8 +24,8 @@ class Migration(migrations.Migration):
24 24 ],
25 25 options={
26 26 'verbose_name_plural': 'Answers',
27   - 'ordering': ('order',),
28 27 'verbose_name': 'Answer',
  28 + 'ordering': ('order',),
29 29 },
30 30 ),
31 31 migrations.CreateModel(
... ...
exam/migrations/0002_auto_20161116_1057.py
... ... @@ -1,30 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
3   -from __future__ import unicode_literals
4   -
5   -from django.conf import settings
6   -from django.db import migrations, models
7   -import django.db.models.deletion
8   -
9   -
10   -class Migration(migrations.Migration):
11   -
12   - initial = True
13   -
14   - dependencies = [
15   - ('exam', '0001_initial'),
16   - migrations.swappable_dependency(settings.AUTH_USER_MODEL),
17   - ]
18   -
19   - operations = [
20   - migrations.AddField(
21   - model_name='answersstudent',
22   - name='student',
23   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student', to=settings.AUTH_USER_MODEL, verbose_name='Student'),
24   - ),
25   - migrations.AddField(
26   - model_name='answer',
27   - name='exam',
28   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='exam.Exam', verbose_name='Answers'),
29   - ),
30   - ]
exam/migrations/0002_auto_20161117_0217.py 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.conf import settings
  6 +from django.db import migrations, models
  7 +import django.db.models.deletion
  8 +
  9 +
  10 +class Migration(migrations.Migration):
  11 +
  12 + initial = True
  13 +
  14 + dependencies = [
  15 + ('exam', '0001_initial'),
  16 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  17 + ]
  18 +
  19 + operations = [
  20 + migrations.AddField(
  21 + model_name='answersstudent',
  22 + name='student',
  23 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student', to=settings.AUTH_USER_MODEL, verbose_name='Student'),
  24 + ),
  25 + migrations.AddField(
  26 + model_name='answer',
  27 + name='exam',
  28 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='exam.Exam', verbose_name='Answers'),
  29 + ),
  30 + ]
... ...
exercise/admin.py
... ... @@ -2,7 +2,7 @@ from django.contrib import admin
2 2 from .models import Exercise
3 3  
4 4 class ExerciseAdmin(admin.ModelAdmin):
5   - list_display = ['name']
6   - search_fields = ['name']
  5 + list_display = ['name_exercise']
  6 + search_fields = ['name_exercise']
7 7  
8 8 admin.site.register(Exercise, ExerciseAdmin)
... ...
exercise/forms.py
... ... @@ -9,11 +9,13 @@ class ExerciseForm(forms.ModelForm):
9 9  
10 10 class Meta:
11 11 model = Exercise
12   - fields = ['name', 'file']
  12 + fields = ['name_exercise', 'description', 'init_date',
  13 + 'end_date', 'file']
13 14  
14 15  
15 16 class UpdateExerciseForm(forms.ModelForm):
16 17  
17 18 class Meta:
18 19 model = Exercise
19   - fields = ['name', 'file']
  20 + fields = ['name_exercise', 'description', 'init_date',
  21 + 'end_date', 'grade', 'file']
... ...
exercise/migrations/0001_initial.py
1 1 # -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
  2 +# Generated by Django 1.10 on 2016-11-17 08:09
3 3 from __future__ import unicode_literals
4 4  
  5 +from decimal import Decimal
  6 +from django.conf import settings
5 7 from django.db import migrations, models
6 8 import django.db.models.deletion
  9 +import exercise.models
7 10  
8 11  
9 12 class Migration(migrations.Migration):
... ... @@ -11,7 +14,9 @@ class Migration(migrations.Migration):
11 14 initial = True
12 15  
13 16 dependencies = [
14   - ('courses', '0001_initial'),
  17 + ('courses', '0002_auto_20161117_0217'),
  18 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  19 + ('core', '0002_auto_20161117_0217'),
15 20 ]
16 21  
17 22 operations = [
... ... @@ -19,8 +24,15 @@ class Migration(migrations.Migration):
19 24 name='Exercise',
20 25 fields=[
21 26 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22   - ('file', models.FileField(upload_to='uploads/%Y/%m/%d')),
23   - ('name', models.CharField(max_length=100)),
  27 + ('name_exercise', models.CharField(max_length=100, verbose_name='Exercise Name')),
  28 + ('description', models.TextField(blank=True, verbose_name='Description')),
  29 + ('init_date', models.DateField(verbose_name='Begin of Subject Date')),
  30 + ('end_date', models.DateField(verbose_name='End of Subject Date')),
  31 + ('grade', models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=20, null=True)),
  32 + ('file', models.FileField(upload_to=exercise.models.file_path)),
  33 + ('file_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='exercise_type', to='core.MimeType', verbose_name='Type file')),
  34 + ('professors', models.ManyToManyField(blank=True, related_name='professors_exercise', to=settings.AUTH_USER_MODEL, verbose_name='Professors')),
  35 + ('students', models.ManyToManyField(blank=True, related_name='subject_exercise', to=settings.AUTH_USER_MODEL, verbose_name='Students')),
24 36 ('topic', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='exercises', to='courses.Topic', verbose_name='Topic')),
25 37 ],
26 38 ),
... ...
exercise/migrations/0002_auto_20161117_0555.py 0 → 100644
... ... @@ -0,0 +1,31 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-11-17 08:55
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.db import migrations, models
  6 +import django.db.models.deletion
  7 +
  8 +
  9 +class Migration(migrations.Migration):
  10 +
  11 + dependencies = [
  12 + ('exercise', '0001_initial'),
  13 + ]
  14 +
  15 + operations = [
  16 + migrations.AlterField(
  17 + model_name='exercise',
  18 + name='file',
  19 + field=models.FileField(upload_to='uploads/%Y/%m/%d'),
  20 + ),
  21 + migrations.AlterField(
  22 + model_name='exercise',
  23 + name='name_exercise',
  24 + field=models.CharField(max_length=100, verbose_name='Name'),
  25 + ),
  26 + migrations.AlterField(
  27 + model_name='exercise',
  28 + name='topic',
  29 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='exercise_topic', to='courses.Topic', verbose_name='Topic'),
  30 + ),
  31 + ]
... ...
exercise/migrations/0003_auto_20161118_2242.py 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-11-19 01:42
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.db import migrations, models
  6 +import django.db.models.deletion
  7 +
  8 +
  9 +class Migration(migrations.Migration):
  10 +
  11 + dependencies = [
  12 + ('exercise', '0002_auto_20161117_0555'),
  13 + ]
  14 +
  15 + operations = [
  16 + migrations.AlterField(
  17 + model_name='exercise',
  18 + name='file_type',
  19 + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='exercise_type', to='core.MimeType', verbose_name='Type file'),
  20 + ),
  21 + ]
... ...
exercise/models.py
1   -from django.db import models
2 1 from courses.models import Topic
  2 +from decimal import Decimal
  3 +from django.db import models
3 4 from django.utils.translation import ugettext_lazy as _
  5 +from users.models import User
  6 +from core.models import MimeType
4 7  
5 8 """
6 9 Function to return the path where the file should be saved
... ... @@ -17,6 +20,17 @@ It represents the Exercises inside topic.
17 20  
18 21  
19 22 class Exercise(models.Model):
20   - topic = models.ForeignKey(Topic, verbose_name=_('Topic'), related_name='exercises')
  23 +
  24 + name_exercise = models.CharField(_('Name'), max_length=100)
  25 + description = models.TextField(_('Description'), blank=True)
  26 + init_date = models.DateField(_('Begin of Subject Date'))
  27 + end_date = models.DateField(_('End of Subject Date'))
  28 + grade = models.DecimalField(max_digits=20, decimal_places=2, default=Decimal('0.00'), null=True)
  29 + topic = models.ForeignKey(Topic, verbose_name=_('Topic'), related_name='exercise_topic')
  30 + professors = models.ManyToManyField(User, verbose_name=_('Professors'), related_name='professors_exercise', blank=True)
  31 + students = models.ManyToManyField(User, verbose_name=_('Students'), related_name='subject_exercise', blank = True)
21 32 file = models.FileField(upload_to='uploads/%Y/%m/%d')
22   - name = models.CharField(max_length=100)
  33 + file_type = models.ForeignKey(MimeType, verbose_name=_('Type file'), related_name='exercise_type',null=True)
  34 +
  35 + def __str__(self):
  36 + return self.name_exercise
23 37 \ No newline at end of file
... ...
exercise/static/js/exercise.js
1   -function get_modal_link(url, id,div_content){
  1 +function get_modal_exercise(url, id,div_content){
2 2 $.get(url, function (data) {
3 3 $(div_content).detach();
4 4 $(div_content).append(data);
... ...
exercise/templates/exercise/card_list_user.html 0 → 100644
... ... @@ -0,0 +1,64 @@
  1 +{% load static i18n list_topic_foruns permission_tags widget_tweaks professor_access list_topic_exercises %}
  2 +
  3 +<div class="col-md-12 col-sm-12 col-lg-12">
  4 + <div class="panel-group accordion ui-accordion ui-widget ui-helper-reset ui-sortable" role="tablist" aria-multiselectable="false">
  5 + <div class="group"><div class="panel panel-default">
  6 + <div class="panel-heading topic ui-sortable-handle" role="tab">
  7 + <div class="row">
  8 + <div class="col-md-1 moreAccordion" data-toggle="collapse" data-parent="#accordion-{{user.id}}" href=".collapseTopic-{{user.id}}" aria-expanded="false" aria-controls="collapseTopic-{{user.id}}">
  9 + <button class="btn btn-default btn-sm caret-square"><i class="fa fa-caret-square-o-down fa-2x" aria-hidden="true"></i></button>
  10 + </div>
  11 + <div class="col-xs-9 col-md-9 titleTopic">
  12 + <a href="" role="button">
  13 + <h4>{{user|capfirst}}</h4>
  14 + </a>
  15 + </div>
  16 + </div>
  17 + </div>
  18 + <div class="panel-collapse collapseTopic-{{user.id}} collapse in" role="tabpanel" aria-labelledby="heading_{{user.id}}" aria-expanded="true" aria-hidden="false">
  19 + <div class="panel-body">
  20 + <div class="row">
  21 + <div class="col-md-4">
  22 + <div class="resource_inline">
  23 + <h4>{% trans 'Grade' %}</h4>
  24 + </div>
  25 + <div class="resource_inline">
  26 + {# dropdown de create exercício #}
  27 + <div class="dropdown">
  28 + <a href="#" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-plus-circle fa-lg" aria-hidden="true"></i></a>
  29 + <ul class="dropdown-menu" aria-labelledby="dLabel">
  30 + <li><a href="javascript:modal.get('{% url 'course:exercise:create_exercise' topic.slug %}', '#createExercisesModal','#requisicoes_ajax')">{% trans 'Give a grade' %}</a></li>
  31 + </ul>
  32 + </div>
  33 + </div>
  34 + </div>
  35 + <div class="col-md-4">
  36 + <div class="resource_inline">
  37 + <h4>{% trans 'Delivery' %}</h4>
  38 + </div>
  39 + {% for exercise in exercises %}
  40 + <li><a href="{{exercise.file.url}}" target="_blank">{{exercise.name_exercise}}</a></li>
  41 + {% endfor %}
  42 + </div>
  43 + <div class="col-md-4">
  44 + <div class="resource_inline">
  45 + <h4>{% trans 'Create' %}</h4>
  46 + </div>
  47 + <div class="resource_inline">
  48 + {# dropdown de create exercício #}
  49 + <div class="dropdown">
  50 + <a href="#" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-plus-circle fa-lg" aria-hidden="true"></i></a>
  51 + <ul class="dropdown-menu" aria-labelledby="dLabel">
  52 + <li><a href="javascript:modal.get('{% url 'course:exercise:create_exercise' topic.slug %}', '#createExercisesModal','#requisicoes_ajax')">{% trans 'Create a specific exercise' %}</a></li>
  53 + </ul>
  54 + </div>
  55 + </div>
  56 + {% include "exercise/create_exercise.html" %}
  57 + </div>
  58 + </div>
  59 + </div>
  60 + </div>
  61 + </div>
  62 + </div>
  63 +</div>
  64 +</div>
0 65 \ No newline at end of file
... ...
exercise/templates/exercise/card_topic_exercises.html 0 → 100644
... ... @@ -0,0 +1,60 @@
  1 +{% load static widget_tweaks i18n %}
  2 +
  3 +<div class="col-lg-4 col-xs-4 col-sm-4">
  4 + <div class="panel panel-default">
  5 + <div class="panel-body">
  6 + <form class="form-horizontal">
  7 + <fieldset>
  8 + <center><legend>{{exercise.name_exercise}}</legend></center>
  9 + <div class="container-fluid">
  10 + <div class="form-group">
  11 + <label class="col-md-2 col-xs-2 col-sm-2 control-label">Describe: </label><br>
  12 + {% if exercise.description%}
  13 + {{exercise.description}}
  14 + {% else %}
  15 + {% trans "Don't have description" %}
  16 + {% endif %}
  17 + </div>
  18 + <div class="form-group">
  19 + <label class="col-md-2 col-xs-2 col-sm-2 control-label">Opening: </label><br>{{exercise.init_date}}
  20 +
  21 + </div>
  22 + <div class="form-group">
  23 + <label class="col-md-2 col-xs-2 col-sm-2 control-label">Ending: </label><br>{{exercise.end_date}}
  24 +
  25 + </div>
  26 + <div class="form-group">
  27 + <label for="nota" class="col-md-2 control-label">NOTA:
  28 + {% if exercise.grade %}
  29 + <div class="col-md-4">
  30 + <p id="nota" class="form-control">
  31 + {{exercise.grade}}
  32 + </p>
  33 + </div>
  34 + {% else %}
  35 + {% trans 'Not yet' %}
  36 + {% endif %}
  37 + </label>
  38 + </div>
  39 + {% if exercise.file %}
  40 + <div class="form-group">
  41 + <label for="DelExc" class="col-md-4 control-label"> <i class="fa fa-file-archive-o fa-3x" aria-hidden="true">
  42 + <a href="{{exercise.file.url}}" target="_blank">{% trans 'File' %}</a>
  43 + </i>
  44 + </div>
  45 + {% else %}
  46 + <p>{% trans 'Exercise not yet' %}</p>
  47 + {% endif %}
  48 + {% if not exercise.grade %}
  49 + <div class="form-group">
  50 + <label class="col-md-6 control-label"><i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>{% trans 'Teacher waiting corretion' %}
  51 + </div>
  52 + {% endif %}
  53 + </div>
  54 +
  55 + </fieldset>
  56 + </form>
  57 +
  58 + </div>
  59 + </div>
  60 +</div>
0 61 \ No newline at end of file
... ...
exercise/templates/exercise/create_exercise.html
... ... @@ -9,75 +9,104 @@
9 9 </div>
10 10 <div class="modal-body">
11 11 <!-- Card -->
12   - <form method="post" action="" id="form-exercise" enctype="multipart/form-data">
  12 + <form class="form-horizontal" method="post" id="form-exercise" enctype="multipart/form-data">
13 13 {% csrf_token %}
14 14 {% if messages %}
15   - {% for message in messages %}
16   - <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert">
17   - <button type="button" class="close" data-dismiss="alert" aria-label="Close">
18   - <span aria-hidden="true">&times;</span>
  15 + {% for message in messages %}
  16 + <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert">
  17 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  18 + <span aria-hidden="true">&times;</span>
  19 + </button>
  20 + <p>{{ message }}</p>
  21 + </div>
  22 + {% endfor %}
  23 + {% endif %}
  24 + <fieldset>
  25 + {% for field in form %}
  26 + <div class="form-group is-empy{% if form.has_error %} has-error {% endif %} is-fileinput">
  27 + <div class="col-md-12">
  28 + {% if field.field.required %}
  29 + <label for="{{ field.auto_id }}" class="control-label">{{ field.label }}<span>*</span></label>
  30 + {% else %}
  31 + <label for="{{ field.auto_id }}" class=" control-label">{{ field.label }}</label>
  32 + {% endif %}
  33 + {% if field.auto_id == 'id_file' %}
  34 + {% render_field field class='form-control input-sm' %}
  35 + <div class="input-group">
  36 + <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your file...' %}">
  37 + <span class="input-group-btn input-group-sm">
  38 + <button type="button" class="btn btn-fab btn-fab-mini">
  39 + <i class="material-icons">attach_file</i>
19 40 </button>
20   - <p>{{ message }}</p>
  41 + </span>
21 42 </div>
22   - {% endfor %}
23   - {% endif %}
24   - {% for field in form %}
25   - <div class ="form-group">
26   - {% if field.field.required %}
27   - <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label>
28   - {% endif %}
29   - {% render_field field class='form-control input-sm' %}
  43 + {% else %}
  44 + {% render_field field class='form-control input-sm' %}
  45 + <span id="helpBlock" class="help-block">{{ field.help_text }}</span>
  46 + {% endif %}
  47 + </div>
  48 +
30 49 {% if field.errors %}
31   - <div class="alert alert-danger alert-dismissible clearfix" role="alert">
32   - <button type="button" class="close" data-dismiss="alert" aria-label="Close">
33   - <span aria-hidden="true">&times;</span>
34   - </button>
35   - <ul>
36   - {% for error in field.errors %}
37   - <li>{{ error }}</li>
38   - {% endfor %}
39   - </ul>
40   - </div>
  50 + <div class="alert alert-danger alert-dismissible clearfix" role="alert">
  51 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  52 + <span aria-hidden="true">&times;</span>
  53 + </button>
  54 + <ul>
  55 + {% for error in field.errors %}
  56 + <li>{{ error }}</li>
  57 + {% endfor %}
  58 + </ul>
  59 + </div>
41 60 {% endif %}
42 61 </div>
43   - {% endfor %}
44   - <div class="form-group">
45   - <button type="button" class="btn btn-raised btn-default " data-dismiss="modal">{% trans "Cancel" %}</button>
46   - <button class="btn btn-raised btn-primary" type="submit">{% trans 'Submit' %}</button>
47   - </div>
48   - <!-- .end Card -->
49   - </div>
50   - </div>
51   - </div>
  62 + {% endfor %}
  63 +
  64 + <div class="form-group">
  65 + <div class="col-md-12 text-center">
  66 + <p><b>{% trans 'The file size shouldnt exceed 10MB' %}</b></p>
  67 + </div>
  68 + </div>
  69 +
  70 + <div class="form-group">
  71 + <div class="col-md-12">
  72 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  73 + <button class="btn btn-raised btn-primary" type="submit">{% trans 'Submit' %}</button>
  74 + </div>
  75 + </div>
  76 + </fieldset>
  77 + </form>
  78 + <!-- .end Card -->
  79 + </div>
  80 + </div>
  81 + </div>
52 82 </div>
53 83 <!-- EndModal -->
54   -<script src="{% static 'js/exercises.js' %}"></script>
55 84 <script type="text/javascript">
56 85 $("#form-exercise").submit(function(event) {
57   - $("#createExercisesModal").modal("hide");
58   - var data = new FormData($('#form-exercise').get(0));
59   - $.ajax({
60   - url: "{% url 'course:exercise:create_exercise' topic.slug %}",
61   - type: $("#form-exercise").attr('method'),
62   - data: data,
63   - cache: false,
64   - processData: false,
65   - contentType: false,
66   - success: function(data) {
67   - $('#requisicoes_ajax').empty();
68   - $('#list-topic{{ topic.id }}-exercises').append(data);
69   - $('#list-topic{{ topic.id }}-exercises-edit').append(data);
70   - alertify.success('Exercise successfully created!')
71   - },
72   - error: function(data){
73   - $('#requisicoes_ajax').empty();
74   - $('#requisicoes_ajax').append(data.responseText);
75   - $('#createExercisesModal').modal('show');
76   - alertify.alert('Invalid exercise, insert a valid one!');
77   - $('div.modal-backdrop.fade.in').remove();
78   - setTimeout(function () { location.reload(1); }, 1000);
79   - }
80   - });
81   - event.preventDefault();
82   - });
  86 + $("#createExercisesModal").modal("hide");
  87 + var data = new FormData($('#form-exercise').get(0));
  88 + $.ajax({
  89 + url: "{% url 'course:exercise:create_exercise' topic.slug %}",
  90 + type: $("#form-exercise").attr('method'),
  91 + data: data,
  92 + cache: false,
  93 + processData: false,
  94 + contentType: false,
  95 + success: function(data) {
  96 + $('#createExercisesModal').modal('hide');
  97 + $('#list-topic{{ topic.id }}-exercises').append(data);
  98 + $('#list-topic{{ topic.id }}-exercises-edit').append(data);
  99 + alertify.success('Exercise successfully created!')
  100 + },
  101 + error: function(data){
  102 + $('#requisicoes_ajax').empty();
  103 + $('#requisicoes_ajax').append(data.responseText);
  104 + $('#createExercisesModal').modal('show');
  105 + alertify.alert('Invalid exercise, insert a valid one!');
  106 + $('div.modal-backdrop.fade.in').remove();
  107 +
  108 + }
  109 + });
  110 + event.preventDefault();
  111 + });
83 112 </script>
... ...
exercise/templates/exercise/exercise_edit.html
1 1 {% load static i18n list_topic_foruns permission_tags %}
2   -<div id="exercise-topic{{ exercise.id }}-exercises-edit">
  2 +<div id="exercise-topic{{ topic.id }}-exercises-edit">
3 3 {% for exercise in exercises %}
4 4 <li class="icon_edit_remove" id = "exercise_edit_icon_{{ exercise.slug }}"> <a href="javascript:modal.get('', '#exercisesModalEdit', '#requisicoes_ajax')"><i class="fa fa-pencil fa-lg" aria-hidden="true"></i></a> <a href="javascript:modal.get('', '#exerciseDeleteModal', '#requisicoes_ajax')"><i class="fa fa-trash fa-lg" aria-hidden="true"></i></a></li>
5 5 <li id = "exercise_edit_{{ exercise.slug }}"><i class="fa fa-link" aria-hidden="true"></i> <a href="javascript:modal.get('', '#viewExerciseModal','#requisicoes_ajax')">{{exercise.name}}</a></li>
... ...
exercise/templates/exercise/render_exercise.html 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<li id="exercise_{{ exercise.slug }}"><i class="material-icons">{{ exercise.file_type.icon }}</i> <a href="{{ exercise.file_url.url }}" target="_blank">{{ exercise.name }}</a></li>
0 2 \ No newline at end of file
... ...
exercise/templatetags/list_topic_exercises.py
... ... @@ -5,21 +5,21 @@ register = template.Library()
5 5  
6 6  
7 7 @register.inclusion_tag('exercise/exercise_list.html')
8   -def list_topic_exercise(request):
  8 +def list_topic_exercise(request, topic):
9 9 context = {
10 10 'request': request,
11 11 }
12   - context['exercises'] = Exercise.objects.all()
  12 + context['exercises'] = Exercise.objects.filter(topic=topic)
13 13  
14 14 return context
15 15  
16 16  
17 17 @register.inclusion_tag('exercise/exercise_edit.html')
18   -def list_topic_exercise_edit(request, exercise):
  18 +def list_topic_exercise_edit(request, topic):
19 19 context = {
20 20 'request': request,
21 21 }
22   - context['exercises'] = Exercise.objects.all()
23   - context['exercise'] = exercise
  22 + context['exercises'] = Exercise.objects.filter(topic = topic)
  23 + context['topic'] = topic
24 24  
25 25 return context
... ...
exercise/views.py
1 1 from .forms import ExerciseForm, UpdateExerciseForm
2 2 from .models import Exercise
3   -from files.utils import mime_type_to_material_icons
4 3 from core.decorators import log_decorator
5 4 from core.mixins import LogMixin, NotificationMixin
6 5 from core.models import Log, MimeType
... ... @@ -13,8 +12,10 @@ from django.core.urlresolvers import reverse_lazy
13 12 from django.shortcuts import render, get_object_or_404, redirect
14 13 from django.urls import reverse
15 14 from django.views import generic
  15 +from files.utils import mime_type_to_material_icons
16 16 from rolepermissions.mixins import HasRoleMixin
17 17 from rolepermissions.verifications import has_role
  18 +from users.models import User
18 19  
19 20  
20 21 class CreateExercise(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMixin, generic.CreateView):
... ... @@ -23,7 +24,7 @@ class CreateExercise(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMix
23 24 log_action = 'create'
24 25 log_component = {}
25 26  
26   - allowed_roles = ['student']
  27 + allowed_roles = ['professor', 'student']
27 28 login_url = reverse_lazy("core:home")
28 29 redirect_field_name = 'next'
29 30 model = Exercise
... ... @@ -35,7 +36,6 @@ class CreateExercise(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMix
35 36 log_resource = "exercise"
36 37 log_action = "create"
37 38 log_context = {}
38   - context_object_name = 'form'
39 39  
40 40 def form_invalid(self, form, **kwargs):
41 41 context = super(CreateExercise, self).form_invalid(form)
... ... @@ -47,19 +47,16 @@ class CreateExercise(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMix
47 47 self.object = form.save(commit = False)
48 48 topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
49 49 self.object.topic = topic
50   -
51   - self.object.name = str(self.object)
52   -
53 50  
54 51 # Set MimeType
55   - exercise = self.request.FILES['exercise_url']
  52 + exercise = self.request.FILES['file']
56 53 try:
57 54 if exercise:
58 55 exercise_type = exercise.content_type
59 56  
60 57 # Check if exist a mimetype in database
61 58 try:
62   - self.object.exercise_type = MimeType.objects.get(typ = exercise_type)
  59 + self.object.file_type = MimeType.objects.get(typ = exercise_type)
63 60 # Create if not
64 61 except:
65 62 mtype = MimeType.objects.create(
... ... @@ -67,11 +64,14 @@ class CreateExercise(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMix
67 64 icon = mime_type_to_material_icons[exercise_type]
68 65 )
69 66 mtype.save()
70   - self.object.exercise_type = mtype
  67 + self.object.file_type = mtype
71 68 except:
72 69 print('Exercise not uploaded')
73 70  
74 71 self.object.save()
  72 + self.object.professors = topic.subject.professors.all()
  73 + self.object.students = topic.subject.students.all()
  74 + self.object.save()
75 75 #CREATE LOG
76 76 self.log_context['topic_id'] = topic.id
77 77 self.log_context['topic_name'] = topic.name
... ... @@ -85,12 +85,12 @@ class CreateExercise(LoginRequiredMixin, HasRoleMixin, LogMixin, NotificationMix
85 85  
86 86  
87 87 #CREATE NOTIFICATION
88   - super(CreateExercise, self).createNotification(message="uploaded a Exercise "+ self.object.name, actor=self.request.user,
89   - resource_name=self.object.name, resource_link= reverse('course:view_topic', args=[self.object.topic.slug]),
  88 + super(CreateExercise, self).createNotification(message="uploaded a Exercise "+ self.object.name_exercise, actor=self.request.user,
  89 + resource_name=self.object.name_exercise, resource_link= reverse('course:view_topic', args=[self.object.topic.slug]),
90 90 users=self.object.topic.subject.students.all())
91 91  
92 92 self.log_context['exercise_id'] = self.object.id
93   - self.log_context['exercise_name'] = self.object.name
  93 + self.log_context['exercise_name'] = self.object.name_exercise
94 94 self.log_context['topic_id'] = self.object.topic.id
95 95 self.log_context['topic_name'] = self.object.topic.name
96 96 self.log_context['topic_slug'] = self.object.topic.slug
... ... @@ -137,7 +137,7 @@ def render_exercise(request, id):
137 137  
138 138 log_context = {}
139 139 log_context['exercise_id'] = exercise.id
140   - log_context['exercise_name'] = exercise.name
  140 + log_context['exercise_name'] = exercise.name_exercise
141 141 log_context['topic_id'] = exercise.topic.id
142 142 log_context['topic_name'] = exercise.topic.name
143 143 log_context['topic_slug'] = exercise.topic.slug
... ...
files/migrations/0001_initial.py
1 1 # -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
3 3 from __future__ import unicode_literals
4 4  
5 5 from django.db import migrations, models
... ... @@ -12,8 +12,8 @@ class Migration(migrations.Migration):
12 12 initial = True
13 13  
14 14 dependencies = [
15   - ('core', '0001_initial'),
16 15 ('courses', '0001_initial'),
  16 + ('core', '0001_initial'),
17 17 ]
18 18  
19 19 operations = [
... ... @@ -27,8 +27,8 @@ class Migration(migrations.Migration):
27 27 ],
28 28 options={
29 29 'verbose_name_plural': 'Files',
30   - 'ordering': ('-id',),
31 30 'verbose_name': 'File',
  31 + 'ordering': ('-id',),
32 32 },
33 33 bases=('courses.material',),
34 34 ),
... ...
files/migrations/0002_topicfile_professor.py
1 1 # -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
3 3 from __future__ import unicode_literals
4 4  
5 5 from django.conf import settings
... ...
forum/migrations/0001_initial.py
1 1 # -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
3 3 from __future__ import unicode_literals
4 4  
5 5 from django.db import migrations, models
... ...
forum/migrations/0002_auto_20161116_1057.py
... ... @@ -1,35 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
3   -from __future__ import unicode_literals
4   -
5   -from django.conf import settings
6   -from django.db import migrations, models
7   -import django.db.models.deletion
8   -
9   -
10   -class Migration(migrations.Migration):
11   -
12   - initial = True
13   -
14   - dependencies = [
15   - ('forum', '0001_initial'),
16   - migrations.swappable_dependency(settings.AUTH_USER_MODEL),
17   - ]
18   -
19   - operations = [
20   - migrations.AddField(
21   - model_name='postanswer',
22   - name='user',
23   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor'),
24   - ),
25   - migrations.AddField(
26   - model_name='post',
27   - name='forum',
28   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Forum', verbose_name='Forum'),
29   - ),
30   - migrations.AddField(
31   - model_name='post',
32   - name='user',
33   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor'),
34   - ),
35   - ]
forum/migrations/0002_auto_20161117_0217.py 0 → 100644
... ... @@ -0,0 +1,35 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.conf import settings
  6 +from django.db import migrations, models
  7 +import django.db.models.deletion
  8 +
  9 +
  10 +class Migration(migrations.Migration):
  11 +
  12 + initial = True
  13 +
  14 + dependencies = [
  15 + ('forum', '0001_initial'),
  16 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  17 + ]
  18 +
  19 + operations = [
  20 + migrations.AddField(
  21 + model_name='postanswer',
  22 + name='user',
  23 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor'),
  24 + ),
  25 + migrations.AddField(
  26 + model_name='post',
  27 + name='forum',
  28 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Forum', verbose_name='Forum'),
  29 + ),
  30 + migrations.AddField(
  31 + model_name='post',
  32 + name='user',
  33 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor'),
  34 + ),
  35 + ]
... ...
links/migrations/0001_initial.py
1 1 # -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
3 3 from __future__ import unicode_literals
4 4  
5 5 from django.db import migrations, models
... ... @@ -19,8 +19,8 @@ class Migration(migrations.Migration):
19 19 name='Link',
20 20 fields=[
21 21 ('material_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Material')),
22   - ('link_url', models.URLField()),
23   - ('link_description', models.CharField(max_length=200)),
  22 + ('link_url', models.URLField(verbose_name='Link_URL')),
  23 + ('link_description', models.CharField(max_length=200, verbose_name='Description')),
24 24 ('image', models.ImageField(blank=True, upload_to='links/')),
25 25 ],
26 26 options={
... ...
links/migrations/0002_auto_20161116_1338.py
... ... @@ -1,25 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 16:38
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   - ('links', '0001_initial'),
12   - ]
13   -
14   - operations = [
15   - migrations.AlterField(
16   - model_name='link',
17   - name='link_description',
18   - field=models.TextField(verbose_name='Description'),
19   - ),
20   - migrations.AlterField(
21   - model_name='link',
22   - name='link_url',
23   - field=models.URLField(verbose_name='Link_URL'),
24   - ),
25   - ]
links/migrations/0003_auto_20161116_1340.py
... ... @@ -1,20 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 16:40
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   - ('links', '0002_auto_20161116_1338'),
12   - ]
13   -
14   - operations = [
15   - migrations.AlterField(
16   - model_name='link',
17   - name='link_description',
18   - field=models.TextField(max_length=200, verbose_name='Description'),
19   - ),
20   - ]
links/migrations/0004_auto_20161116_1341.py
... ... @@ -1,20 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 16:41
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   - ('links', '0003_auto_20161116_1340'),
12   - ]
13   -
14   - operations = [
15   - migrations.AlterField(
16   - model_name='link',
17   - name='link_description',
18   - field=models.CharField(max_length=200, verbose_name='Description'),
19   - ),
20   - ]
poll/migrations/0001_initial.py
1 1 # -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
3 3 from __future__ import unicode_literals
4 4  
5 5 from django.db import migrations, models
... ... @@ -24,8 +24,8 @@ class Migration(migrations.Migration):
24 24 ],
25 25 options={
26 26 'verbose_name_plural': 'Answers',
27   - 'ordering': ('order',),
28 27 'verbose_name': 'Answer',
  28 + 'ordering': ('order',),
29 29 },
30 30 ),
31 31 migrations.CreateModel(
... ...
poll/migrations/0002_auto_20161116_1057.py
... ... @@ -1,30 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
3   -from __future__ import unicode_literals
4   -
5   -from django.conf import settings
6   -from django.db import migrations, models
7   -import django.db.models.deletion
8   -
9   -
10   -class Migration(migrations.Migration):
11   -
12   - initial = True
13   -
14   - dependencies = [
15   - ('poll', '0001_initial'),
16   - migrations.swappable_dependency(settings.AUTH_USER_MODEL),
17   - ]
18   -
19   - operations = [
20   - migrations.AddField(
21   - model_name='answersstudent',
22   - name='student',
23   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundent', to=settings.AUTH_USER_MODEL, verbose_name='Student'),
24   - ),
25   - migrations.AddField(
26   - model_name='answer',
27   - name='poll',
28   - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='poll.Poll', verbose_name='Answers'),
29   - ),
30   - ]
poll/migrations/0002_auto_20161117_0217.py 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.conf import settings
  6 +from django.db import migrations, models
  7 +import django.db.models.deletion
  8 +
  9 +
  10 +class Migration(migrations.Migration):
  11 +
  12 + initial = True
  13 +
  14 + dependencies = [
  15 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  16 + ('poll', '0001_initial'),
  17 + ]
  18 +
  19 + operations = [
  20 + migrations.AddField(
  21 + model_name='answersstudent',
  22 + name='student',
  23 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundent', to=settings.AUTH_USER_MODEL, verbose_name='Student'),
  24 + ),
  25 + migrations.AddField(
  26 + model_name='answer',
  27 + name='poll',
  28 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='poll.Poll', verbose_name='Answers'),
  29 + ),
  30 + ]
... ...
users/locale/pt_BR/LC_MESSAGES/django.po
... ... @@ -8,7 +8,7 @@ msgid &quot;&quot;
8 8 msgstr ""
9 9 "Project-Id-Version: PACKAGE VERSION\n"
10 10 "Report-Msgid-Bugs-To: \n"
11   -"POT-Creation-Date: 2016-10-26 14:47-0300\n"
  11 +"POT-Creation-Date: 2016-11-17 09:46-0300\n"
12 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14 14 "Language-Team: LANGUAGE <LL@li.org>\n"
... ... @@ -18,19 +18,19 @@ msgstr &quot;&quot;
18 18 "Content-Transfer-Encoding: 8bit\n"
19 19 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
20 20  
21   -#: users/forms.py:60
  21 +#: .\forms.py:60
22 22 msgid "Please enter a valid CPF"
23 23 msgstr "Por favor, insira um CPF válido"
24 24  
25   -#: users/forms.py:67
  25 +#: .\forms.py:66
26 26 msgid "Please enter a valid date"
27 27 msgstr "Por favor, insira uma data válida"
28 28  
29   -#: users/models.py:11 users/templates/users/profile.html:61
  29 +#: .\models.py:11 .\templates\users\profile.html:64
30 30 msgid "Login"
31 31 msgstr "Login"
32 32  
33   -#: users/models.py:14
  33 +#: .\models.py:14
34 34 msgid ""
35 35 "Type a valid username. This fields should only contain letters, numbers and "
36 36 "the characteres: @/./+/-/_ ."
... ... @@ -38,361 +38,359 @@ msgstr &quot;&quot;
38 38 "Digite um nome de usuário válido. Esse campo deve conter apenas letras, "
39 39 "números e os caracteres: @/./+/-/_ ."
40 40  
41   -#: users/models.py:17
  41 +#: .\models.py:17
42 42 msgid ""
43 43 "A short name that will be used to identify you in the platform and to access "
44 44 "it"
45 45 msgstr ""
46 46 "Um nome curto que será usado para se identificar no acesso à plataforma"
47 47  
48   -#: users/models.py:18
  48 +#: .\models.py:18
49 49 msgid "Mail"
50 50 msgstr "Email"
51 51  
52   -#: users/models.py:19 users/templates/list_users.html:67
  52 +#: .\models.py:19 .\templates\list_users.html:58
  53 +#: .\templates\users\profile.html:60
53 54 msgid "Name"
54 55 msgstr "Nome"
55 56  
56   -#: users/models.py:20
  57 +#: .\models.py:20
57 58 msgid "City"
58 59 msgstr "Cidade"
59 60  
60   -#: users/models.py:21
  61 +#: .\models.py:21
61 62 msgid "State"
62 63 msgstr "Estado"
63 64  
64   -#: users/models.py:22 users/templates/users/profile.html:105
  65 +#: .\models.py:22 .\templates\users\profile.html:108
65 66 msgid "Gender"
66 67 msgstr "Gênero"
67 68  
68   -#: users/models.py:22
  69 +#: .\models.py:22
69 70 msgid "Male"
70 71 msgstr "Masculino"
71 72  
72   -#: users/models.py:22
  73 +#: .\models.py:22
73 74 msgid "Female"
74 75 msgstr "Feminino"
75 76  
76   -#: users/models.py:23
77   -msgid "Image"
78   -msgstr "Imagem"
  77 +#: .\models.py:23
  78 +msgid "Photo"
  79 +msgstr "Foto"
79 80  
80   -#: users/models.py:24 users/templates/users/profile.html:109
  81 +#: .\models.py:24 .\templates\users\profile.html:112
81 82 msgid "Birth Date"
82 83 msgstr "Data de nascimento"
83 84  
84   -#: users/models.py:25
  85 +#: .\models.py:25
85 86 msgid "Phone"
86 87 msgstr "Telefone"
87 88  
88   -#: users/models.py:26
89   -msgid "Cpf"
  89 +#: .\models.py:26 .\templates\users\profile.html:89
  90 +msgid "CPF"
90 91 msgstr "CPF"
91 92  
92   -#: users/models.py:27
  93 +#: .\models.py:27
93 94 msgid "Type"
94 95 msgstr "Tipo"
95 96  
96   -#: users/models.py:27
  97 +#: .\models.py:27
97 98 msgid "Professor"
98 99 msgstr "Professor"
99 100  
100   -#: users/models.py:27 users/templates/users/profile.html:81
  101 +#: .\models.py:27 .\templates\users\profile.html:84
101 102 msgid "Student"
102 103 msgstr "Aluno"
103 104  
104   -#: users/models.py:28
  105 +#: .\models.py:28
105 106 msgid "Titration"
106 107 msgstr "Título"
107 108  
108   -#: users/models.py:29
  109 +#: .\models.py:29
109 110 msgid "Year of titration"
110 111 msgstr "Ano do título"
111 112  
112   -#: users/models.py:30
113   -msgid "Institution where he had titration"
114   -msgstr "Instituição o qual obteve o título"
  113 +#: .\models.py:30 .\templates\users\profile.html:128
  114 +msgid "Institution"
  115 +msgstr "Instituição"
115 116  
116   -#: users/models.py:31 users/templates/users/profile.html:135
  117 +#: .\models.py:31 .\templates\users\profile.html:136
117 118 msgid "Curriculum"
118 119 msgstr "Currículo"
119 120  
120   -#: users/models.py:32
  121 +#: .\models.py:32
121 122 msgid "Create Date"
122 123 msgstr "Data de criação"
123 124  
124   -#: users/models.py:33
125   -msgid "Administrador"
  125 +#: .\models.py:33 .\templates\users\index.html:46
  126 +#: .\templates\users\view.html:19
  127 +msgid "Administrator"
126 128 msgstr "Administrador"
127 129  
128   -#: users/models.py:34
  130 +#: .\models.py:34
129 131 msgid "Active"
130 132 msgstr "Ativo"
131 133  
132   -#: users/models.py:42
  134 +#: .\models.py:42
133 135 msgid "User"
134 136 msgstr "Usuário"
135 137  
136   -#: users/models.py:43
  138 +#: .\models.py:43
137 139 msgid "Users"
138 140 msgstr "Usuários"
139 141  
140   -#: users/templates/list_users.html:15 users/templates/users/profile.html:17
141   -msgid "Menu"
142   -msgstr "Menu"
143   -
144   -#: users/templates/list_users.html:19 users/templates/users/index.html:7
145   -#: users/templates/users/view.html:7
146   -msgid "Home"
147   -msgstr "Início"
148   -
149   -#: users/templates/list_users.html:20
150   -msgid "Add user"
  142 +#: .\templates\list_users.html:14 .\templates\users\index.html:13
  143 +#: .\templates\users\profile.html:16
  144 +msgid "Add User"
151 145 msgstr "Adicionar usuário"
152 146  
153   -#: users/templates/list_users.html:21
154   -msgid "Send email"
155   -msgstr "Enviar e-mail"
156   -
157   -#: users/templates/list_users.html:41
  147 +#: .\templates\list_users.html:32
158 148 msgid "Search..."
159 149 msgstr "Pesquisar..."
160 150  
161   -#: users/templates/list_users.html:45
162   -msgid "Search"
163   -msgstr "Pesquisar"
164   -
165   -#: users/templates/list_users.html:68
  151 +#: .\templates\list_users.html:59
166 152 msgid "Profile"
167 153 msgstr "Perfil"
168 154  
169   -#: users/templates/list_users.html:69 users/templates/users/profile.html:65
  155 +#: .\templates\list_users.html:60 .\templates\users\profile.html:68
170 156 msgid "Email"
171 157 msgstr "Email"
172 158  
173   -#: users/templates/list_users.html:70
  159 +#: .\templates\list_users.html:61
174 160 msgid "Contact"
175 161 msgstr "Contato"
176 162  
177   -#: users/templates/list_users.html:72
  163 +#: .\templates\list_users.html:63
178 164 msgid "Edit"
179 165 msgstr "Editar"
180 166  
181   -#: users/templates/list_users.html:73 users/templates/list_users.html:91
  167 +#: .\templates\list_users.html:64 .\templates\list_users.html:82
182 168 msgid "Delete"
183 169 msgstr "Apagar"
184 170  
185   -#: users/templates/list_users.html:84
  171 +#: .\templates\list_users.html:75
186 172 msgid "Confirm delete"
187 173 msgstr "Confirmar"
188 174  
189   -#: users/templates/list_users.html:87
  175 +#: .\templates\list_users.html:78
190 176 msgid "Are you sure you want to delete the user"
191 177 msgstr "Você tem certeza que deseja deletar o usuário"
192 178  
193   -#: users/templates/list_users.html:90
194   -#: users/templates/users/change_password.html:47
195   -#: users/templates/users/create.html:130
196   -#: users/templates/users/edit_profile.html:79
197   -#: users/templates/users/remove_account.html:35
198   -#: users/templates/users/update.html:83
  179 +#: .\templates\list_users.html:81 .\templates\users\change_password.html:47
  180 +#: .\templates\users\create.html:130 .\templates\users\edit_profile.html:102
  181 +#: .\templates\users\remove_account.html:35 .\templates\users\update.html:83
199 182 msgid "Cancel"
200 183 msgstr "Cancelar"
201 184  
202   -#: users/templates/list_users.html:103 users/templates/users/index.html:74
  185 +#: .\templates\list_users.html:94 .\templates\users\index.html:64
203 186 msgid "No users found"
204 187 msgstr "Nenhum usuário encontrado"
205 188  
206   -#: users/templates/users/change_password.html:31
207   -#, fuzzy
208   -#| msgid "Password"
  189 +#: .\templates\users\change_password.html:31
209 190 msgid "Current Password"
210   -msgstr "Senha"
  191 +msgstr "Senha atual"
211 192  
212   -#: users/templates/users/change_password.html:35
  193 +#: .\templates\users\change_password.html:35
213 194 #, fuzzy
214 195 #| msgid "Password"
215 196 msgid "New Password"
216 197 msgstr "Senha"
217 198  
218   -#: users/templates/users/change_password.html:39
  199 +#: .\templates\users\change_password.html:39
219 200 msgid "Confirmation"
220 201 msgstr "Confirmação"
221 202  
222   -#: users/templates/users/change_password.html:44
223   -#: users/templates/users/create.html:127
224   -#: users/templates/users/edit_profile.html:76
225   -#: users/templates/users/update.html:80
  203 +#: .\templates\users\change_password.html:44 .\templates\users\create.html:127
  204 +#: .\templates\users\edit_profile.html:99 .\templates\users\update.html:80
226 205 msgid "Save"
227 206 msgstr "Salvar"
228 207  
229   -#: users/templates/users/create.html:51
230   -#: users/templates/users/edit_profile.html:39
231   -#: users/templates/users/update.html:42
  208 +#: .\templates\users\create.html:51
232 209 msgid "Choose your photo..."
233 210 msgstr "Envie sua foto..."
234 211  
235   -#: users/templates/users/create.html:67
  212 +#: .\templates\users\create.html:67 .\templates\users\edit_profile.html:47
  213 +#: .\templates\users\update.html:42
236 214 msgid "Choose your file..."
237   -msgstr "Envie um arquivo..."
238   -
239   -#: users/templates/users/index.html:8
240   -msgid "Manage Users"
241   -msgstr "Gerenciar Usuários"
242   -
243   -#: users/templates/users/index.html:15 users/templates/users/view.html:15
244   -msgid "System Users"
245   -msgstr "Usuários do sistema"
246   -
247   -#: users/templates/users/index.html:18 users/templates/users/view.html:18
248   -msgid "New Account"
249   -msgstr "Nova conta"
  215 +msgstr "Escolha o arquivo..."
250 216  
251   -#: users/templates/users/index.html:21 users/templates/users/view.html:27
252   -msgid "Send Mail"
253   -msgstr "Enviar email"
254   -
255   -#: users/templates/users/index.html:56 users/templates/users/view.html:39
256   -msgid "Administrator"
257   -msgstr "Administrador"
258   -
259   -#: users/templates/users/profile.html:21
260   -#, fuzzy
261   -#| msgid "Home"
262   -msgid "Home page"
  217 +#: .\templates\users\index.html:7 .\templates\users\view.html:7
  218 +msgid "Home"
263 219 msgstr "Início"
264 220  
265   -#: users/templates/users/profile.html:22
266   -#, fuzzy
267   -#| msgid "Edit Profile"
268   -msgid "View Profile"
269   -msgstr "Editar perfil"
270   -
271   -#: users/templates/users/profile.html:23
272   -msgid "Edit Profile"
273   -msgstr "Editar perfil"
274   -
275   -#: users/templates/users/profile.html:24
276   -#, fuzzy
277   -#| msgid "Password"
278   -msgid "Change Password"
279   -msgstr "Senha"
280   -
281   -#: users/templates/users/profile.html:25
282   -#, fuzzy
283   -#| msgid "New Account"
284   -msgid "Remove account"
285   -msgstr "Nova conta"
  221 +#: .\templates\users\index.html:8
  222 +msgid "Manage Users"
  223 +msgstr "Gerenciar Usuários"
286 224  
287   -#: users/templates/users/profile.html:53
  225 +#: .\templates\users\profile.html:51
288 226 #, fuzzy
289 227 #| msgid "State"
290 228 msgid "Status"
291 229 msgstr "Estado"
292 230  
293   -#: users/templates/users/profile.html:77
  231 +#: .\templates\users\profile.html:53
  232 +msgid "Online"
  233 +msgstr "Conectado"
  234 +
  235 +#: .\templates\users\profile.html:55
  236 +msgid "OffLine"
  237 +msgstr "Desconectado"
  238 +
  239 +#: .\templates\users\profile.html:80
294 240 msgid "User role"
295 241 msgstr "Tipo de usuário"
296 242  
297   -#: users/templates/users/profile.html:79
  243 +#: .\templates\users\profile.html:82
298 244 msgid "Teacher"
299 245 msgstr "Professor"
300 246  
301   -#: users/templates/users/profile.html:86
302   -msgid "CPF"
303   -msgstr "CPF"
304   -
305   -#: users/templates/users/profile.html:91
306   -msgid "doesn't posssess CPF"
  247 +#: .\templates\users\profile.html:94
  248 +#, fuzzy
  249 +#| msgid "doesn't posssess CPF"
  250 +msgid "doesn't possess CPF"
307 251 msgstr "Não possui CPF"
308 252  
309   -#: users/templates/users/profile.html:96
  253 +#: .\templates\users\profile.html:99
310 254 msgid "Phone Number"
311 255 msgstr "Telefone"
312 256  
313   -#: users/templates/users/profile.html:100
314   -msgid "doesn't posssess Phone"
  257 +#: .\templates\users\profile.html:103
  258 +#, fuzzy
  259 +#| msgid "doesn't posssess Phone"
  260 +msgid "doesn't possess Phone"
315 261 msgstr "Não possui telefone"
316 262  
317   -#: users/templates/users/profile.html:113
  263 +#: .\templates\users\profile.html:116
318 264 msgid "State and City"
319 265 msgstr "Estado e cidade"
320 266  
321   -#: users/templates/users/profile.html:117
  267 +#: .\templates\users\profile.html:120
322 268 msgid "Title"
323 269 msgstr "Título"
324 270  
325   -#: users/templates/users/profile.html:121
  271 +#: .\templates\users\profile.html:124
326 272 msgid "Year"
327 273 msgstr "Ano"
328 274  
329   -#: users/templates/users/profile.html:125
330   -msgid "Institution"
331   -msgstr "Instituição"
332   -
333   -#: users/templates/users/profile.html:129
  275 +#: .\templates\users\profile.html:132
334 276 msgid "Didn't inform institution"
335 277 msgstr "Não informou a instituição"
336 278  
337   -#: users/templates/users/profile.html:139
  279 +#: .\templates\users\profile.html:142
338 280 msgid "Didn't upload any curriculum"
339 281 msgstr "Não enviou nenhum currículo"
340 282  
341   -#: users/templates/users/remove_account.html:28
  283 +#: .\templates\users\remove_account.html:28
342 284 msgid "Are you sure you want delete this account?"
343 285 msgstr "Voce tem certeza que deseja remover esta conta?"
344 286  
345   -#: users/templates/users/remove_account.html:29
346   -msgid ""
347   -"All data will be lost and havent how recover it."
348   -msgstr "Todos os seus dados serão removidos e não haverá como recupera-los posteriormente."
  287 +#: .\templates\users\remove_account.html:29
  288 +msgid "All data will be lost and havent how recover it."
  289 +msgstr ""
  290 +"Todos os seus dados serão removidos e não haverá como recupera-los "
  291 +"posteriormente."
349 292  
350   -#: users/templates/users/remove_account.html:32
  293 +#: .\templates\users\remove_account.html:32
351 294 msgid "Remove"
352 295 msgstr "Remover"
353 296  
354   -#: users/templates/users/view.html:21
355   -msgid "View User Account"
356   -msgstr "Visualizar perfil"
357   -
358   -#: users/templates/users/view.html:24
359   -msgid "Edit User Account"
360   -msgstr "Editar perfil"
  297 +#: .\templates\users\search.html:131
  298 +msgid "poll"
  299 +msgstr ""
361 300  
362   -#: users/templates/users/view.html:43
  301 +#: .\templates\users\view.html:23
363 302 msgid "Mail:"
364 303 msgstr "E-mail"
365 304  
366   -#: users/templates/users/view.html:46
  305 +#: .\templates\users\view.html:26
367 306 msgid "Phone:"
368 307 msgstr "Telefone"
369 308  
370   -#: users/templates/users/view.html:49
  309 +#: .\templates\users\view.html:29
371 310 msgid "Cpf:"
372 311 msgstr "CPF"
373 312  
374   -#: users/templates/users/view.html:52
  313 +#: .\templates\users\view.html:32
375 314 msgid "Birth date:"
376 315 msgstr "Data de nascimento:"
377 316  
378   -#: users/views.py:55
  317 +#: .\views.py:70
379 318 msgid "User created successfully!"
380 319 msgstr "Usuário criado com sucesso!"
381 320  
382   -#: users/views.py:84
  321 +#: .\views.py:99
383 322 msgid "User edited successfully!"
384 323 msgstr "Usuário editado com sucesso!"
385 324  
386   -#: users/views.py:101
  325 +#: .\views.py:116 .\views.py:122
387 326 #, fuzzy
388 327 #| msgid "User edited successfully!"
389 328 msgid "User deleted Successfully!"
390 329 msgstr "Usuário editado com sucesso!"
391 330  
392   -#: users/views.py:126
  331 +#: .\views.py:152
393 332 msgid "Profile edited successfully!"
394 333 msgstr "Perfil editado com sucesso!"
395 334  
  335 +#~ msgid "Administrador"
  336 +#~ msgstr "Administrador"
  337 +
  338 +#~ msgid "Image"
  339 +#~ msgstr "Imagem"
  340 +
  341 +#~ msgid "Cpf"
  342 +#~ msgstr "CPF"
  343 +
  344 +#~ msgid "Institution where he had titration"
  345 +#~ msgstr "Instituição o qual obteve o título"
  346 +
  347 +#~ msgid "Menu"
  348 +#~ msgstr "Menu"
  349 +
  350 +#~ msgid "Send email"
  351 +#~ msgstr "Enviar e-mail"
  352 +
  353 +#~ msgid "Search"
  354 +#~ msgstr "Pesquisar"
  355 +
  356 +#~ msgid "System Users"
  357 +#~ msgstr "Usuários do sistema"
  358 +
  359 +#~ msgid "New Account"
  360 +#~ msgstr "Nova conta"
  361 +
  362 +#~ msgid "Send Mail"
  363 +#~ msgstr "Enviar email"
  364 +
  365 +#, fuzzy
  366 +#~| msgid "Home"
  367 +#~ msgid "Home page"
  368 +#~ msgstr "Início"
  369 +
  370 +#, fuzzy
  371 +#~| msgid "Edit Profile"
  372 +#~ msgid "View Profile"
  373 +#~ msgstr "Editar perfil"
  374 +
  375 +#~ msgid "Edit Profile"
  376 +#~ msgstr "Editar perfil"
  377 +
  378 +#, fuzzy
  379 +#~| msgid "Password"
  380 +#~ msgid "Change Password"
  381 +#~ msgstr "Senha"
  382 +
  383 +#, fuzzy
  384 +#~| msgid "New Account"
  385 +#~ msgid "Remove account"
  386 +#~ msgstr "Remover conta"
  387 +
  388 +#~ msgid "View User Account"
  389 +#~ msgstr "Visualizar perfil"
  390 +
  391 +#~ msgid "Edit User Account"
  392 +#~ msgstr "Editar perfil"
  393 +
396 394 #~ msgid "New User"
397 395 #~ msgstr "Novo usuário"
398 396  
... ...
users/migrations/0001_initial.py
1 1 # -*- coding: utf-8 -*-
2   -# Generated by Django 1.10 on 2016-11-16 13:57
  2 +# Generated by Django 1.10 on 2016-11-17 05:17
3 3 from __future__ import unicode_literals
4 4  
5 5 import django.contrib.auth.models
... ...
users/models.py
... ... @@ -30,7 +30,7 @@ class User(AbstractBaseUser, PermissionsMixin):
30 30 institution = models.CharField(_('Institution'), max_length = 50, blank=True, null=True)
31 31 curriculum = models.FileField(verbose_name = _('Curriculum'), upload_to='users/curriculum/', null=True, blank=True)
32 32 date_created = models.DateTimeField(_('Create Date'), auto_now_add = True)
33   - is_staff = models.BooleanField(_('Administrador'), default = False)
  33 + is_staff = models.BooleanField(_('Administrator'), default = False)
34 34 is_active = models.BooleanField(_('Active'), default = True)
35 35  
36 36 USERNAME_FIELD = 'username'
... ...
users/templates/list_users.html
... ... @@ -10,9 +10,6 @@
10 10 {% endblock %}
11 11  
12 12 {% block menu %}
13   - {% if user|has_role:'system_admin' %}
14   - <li> <a href="{% url 'users:create' %}">{% trans 'Add User' %}</a></li>
15   - {% endif %}
16 13 {% endblock %}
17 14  
18 15 {% block content %}
... ...
users/templates/users/create.html
... ... @@ -38,8 +38,8 @@
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:'SHORT_DATE_FORMAT'}}">
42 41  
  42 + {% render_field field class='form-control date-picker' %}
43 43 {% elif field.auto_id == 'id_image' %}
44 44 {% if field.field.required %}
45 45 <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label>
... ... @@ -71,10 +71,10 @@
71 71 </button>
72 72 </span>
73 73 </div>
74   - {% elif field.auto_id == 'id_is_staff' or field.auto_id == 'id_is_active' %}
  74 + {% elif field.auto_id == 'id_is_staff' or field.auto_id == 'id_is_active' %}
75 75 <div class="checkbox">
76 76 <label for="{{ field.auto_id }}">
77   - {% render_field field %}<span class="checkbox-material"><span class="check"></span></span> {{field.label}}
  77 + {% render_field field %} {{field.label}}
78 78 </label>
79 79 </div>
80 80 {% elif field.auto_id == 'id_cpf' %}
... ... @@ -123,10 +123,10 @@
123 123 {% endif %}
124 124 </div>
125 125 {% endfor %}
126   - <div class="col-md-offset-2 col-md-2 col-sm-2 col-xs-2">
  126 + <div class="col-md-5 col-xs-6 col-sm-6 col-lg-5 text-center">
127 127 <input type="submit" value="{% trans 'Save' %}" class="btn btn-raised btn-success" onclick="validarCpfSemAlert(id_cpf, CPF, idElementoMensagemErro)'" />
128 128 </div>
129   - <div class="col-md-offset-4 col-md-2 col-sm-2 col-xs-2">
  129 + <div class="col-md-5 col-xs-6 col-sm-6 col-lg-5 text-center">
130 130 <a href="{% url 'users:manage' %}" class="btn btn-raised btn-danger" >{% trans 'Cancel' %}</a>
131 131 </div>
132 132 </form>
... ... @@ -136,4 +136,11 @@
136 136 </br>
137 137 </br>
138 138 </br>
  139 +<script type="text/javascript">
  140 +var locale = navigator.language || navigator.userLanguage;
  141 +
  142 +$('.date-picker').datepicker({
  143 + language: locale,
  144 +});
  145 +</script>
139 146 {% endblock %}
... ...
users/templates/users/index.html
... ... @@ -10,7 +10,7 @@
10 10 {% endblock %}
11 11  
12 12 {% block menu %}
13   - <li> <a href="{% url 'users:create' %}">{% trans 'Add User' %}</a></li>
  13 +
14 14 {% endblock %}
15 15  
16 16 {% block content %}
... ...
users/views.py
... ... @@ -39,7 +39,7 @@ class UsersListView(HasRoleMixin, LoginRequiredMixin, generic.ListView):
39 39 search = self.request.GET.get('search', None)
40 40  
41 41 if search is None:
42   - users = User.objects.exclude(username = self.request.user.username)
  42 + users = User.objects.all().order_by('name').exclude( username = self.request.user.username)
43 43 else:
44 44 users = User.objects.filter(Q(username = search) | Q(name = search) | Q(name__icontains = search) | Q(username__icontains = search)).exclude( username = self.request.user.username)
45 45  
... ... @@ -67,9 +67,13 @@ class Create(HasRoleMixin, LoginRequiredMixin, generic.edit.CreateView):
67 67  
68 68 self.object.save()
69 69  
70   - messages.success(self.request, _('User created successfully!'))
  70 + messages.success(self.request, _('User ')+self.object.name+(' created successfully!'))
71 71  
72 72 return super(Create, self).form_valid(form)
  73 + def get_context_data (self, **kwargs):
  74 + context = super(Create, self).get_context_data(**kwargs)
  75 + context['title'] = _("Add User")
  76 + return context
73 77  
74 78 class Update(HasRoleMixin, LoginRequiredMixin, generic.UpdateView):
75 79  
... ... @@ -96,7 +100,7 @@ class Update(HasRoleMixin, LoginRequiredMixin, generic.UpdateView):
96 100  
97 101 self.object.save()
98 102  
99   - messages.success(self.request, _('User edited successfully!'))
  103 + messages.success(self.request, _('User ')+self.object.name+(' updated successfully!'))
100 104  
101 105 return super(Update, self).form_valid(form)
102 106  
... ... @@ -243,4 +247,3 @@ class UserViewSet(viewsets.ModelViewSet):
243 247 queryset = User.objects.all()
244 248 serializer_class = UserSerializer
245 249 permissions_classes = (IsAuthenticatedOrReadOnly,)
246   -
... ...