Commit d4a07c6ffe639e41ab172ceddcf08b1c4f9541d3
Exists in
master
and in
5 other branches
correção do template reset password #204
Showing
95 changed files
with
2072 additions
and
1113 deletions
Show diff stats
amadeus/roles.py
amadeus/settings.py
... | ... | @@ -56,7 +56,6 @@ INSTALLED_APPS = [ |
56 | 56 | 'forum', |
57 | 57 | 'poll', |
58 | 58 | 'links', |
59 | - 'exam', | |
60 | 59 | 'files', |
61 | 60 | |
62 | 61 | ] |
... | ... | @@ -224,6 +223,9 @@ S3DIRECT_DESTINATIONS = { |
224 | 223 | |
225 | 224 | } |
226 | 225 | |
226 | +# FILE UPLOAD | |
227 | +MAX_UPLOAD_SIZE = 10485760 | |
228 | + | |
227 | 229 | try: |
228 | 230 | from .local_settings import * |
229 | 231 | except ImportError: | ... | ... |
... | ... | @@ -0,0 +1,43 @@ |
1 | +//controles do modal | |
2 | +$(window).ready(function() { // utilizado para abrir o modal quando tiver tido algum erro no preenchimento do formulario | |
3 | + if($('.not_submited').length){ | |
4 | + $('#poll').modal('show'); | |
5 | + } | |
6 | +}); | |
7 | +var Answer = { | |
8 | + init: function(url) { // utilizado para adicionar um novo campo de resposta | |
9 | + $.get(url, function(data){ | |
10 | + $("#form").append(data); | |
11 | + var cont = 1; | |
12 | + $("#form div div div input").each(function(){ | |
13 | + $(this).attr('name',cont++); | |
14 | + }); | |
15 | + }); | |
16 | + } | |
17 | +}; | |
18 | + | |
19 | +var Submite = { | |
20 | + post: function(url,dados){ | |
21 | + $('#poll').modal('hide'); | |
22 | + $.post(url,dados, function(data){ | |
23 | + }).fail(function(data){ | |
24 | + $("div.modal-backdrop.fade.in").remove(); | |
25 | + $("#modal_poll").empty(); | |
26 | + $("#modal_poll").append(data.responseText); | |
27 | + }); | |
28 | + }, | |
29 | + remove: function(url,dados, id_li_link){ | |
30 | + $('#poll').modal('hide'); | |
31 | + $.post(url,dados, function(data){ | |
32 | + $(id_li_link).remove(); | |
33 | + $("#modal_poll").empty(); | |
34 | + $("div.modal-backdrop.fade.in").remove(); | |
35 | + }).fail(function(){ | |
36 | + $("#modal_poll").empty(); | |
37 | + $("#modal_poll").append(data); | |
38 | + $('#poll').modal('show'); | |
39 | + }); | |
40 | + } | |
41 | +} | |
42 | + | |
43 | +alert("essfd"); | ... | ... |
... | ... | @@ -0,0 +1,14 @@ |
1 | +var Modal = { | |
2 | + get: function (url, id_modal, id_div_modal){ | |
3 | + $.get(url, function(data){ | |
4 | + if($(id_modal).length){ | |
5 | + $(id_div_modal).empty(); | |
6 | + $(id_div_modal).append(data); | |
7 | + } else { | |
8 | + $(id_div_modal).append(data); | |
9 | + } | |
10 | + $(id_modal).modal('show'); | |
11 | + }); | |
12 | + } | |
13 | +}; | |
14 | +alert("req"); | ... | ... |
... | ... | @@ -0,0 +1,12 @@ |
1 | +//deve ser importado apenas depois do html | |
2 | +$( "#form" ).sortable({ // utilizado para fazer a re-organização das respostas | |
3 | + delay: 100, | |
4 | + distance: 5, | |
5 | + update: function( event, ui ) { | |
6 | + var cont = 1; | |
7 | + $("#form div div div input").each(function(){ | |
8 | + $(this).attr('name',cont++); | |
9 | + }); | |
10 | + }, | |
11 | +}); | |
12 | +alert("sort"); | ... | ... |
app/templates/app/base.html
... | ... | @@ -1,22 +0,0 @@ |
1 | -{% extends 'base.html' %} | |
2 | - | |
3 | -{% load static i18n %} | |
4 | - | |
5 | -{% block menu_top %} | |
6 | - <ul class="nav navbar-nav"> | |
7 | - <li class="active"> | |
8 | - <a href="{% url 'home' %}">Home</a> | |
9 | - </li> | |
10 | - <li><a href="#contact">{% trans 'The Project' %}</a></li> | |
11 | - <li><a href="#contact">{% trans 'CCTE Group' %}</a></li> | |
12 | - <li class="divider-vertical"></li> | |
13 | - <li class="dropdown"> | |
14 | - <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{% trans 'Hi' %}, {{ user }} <span class="caret"></span></a> | |
15 | - <ul class="dropdown-menu"> | |
16 | - <li><a href="{% url 'app:users:profile' %}">{% trans 'See Profile' %}</a></li> | |
17 | - <li><a href="#">{% trans 'Settings' %}</a></li> | |
18 | - <li><a href="{% url 'logout' %}">{% trans 'Logout' %}</a></li> | |
19 | - </ul> | |
20 | - </li> | |
21 | - </ul> | |
22 | -{% endblock %} | |
23 | 0 | \ No newline at end of file |
app/templates/app/index.html
... | ... | @@ -1,181 +0,0 @@ |
1 | -{% extends 'app/base.html' %} | |
2 | - | |
3 | -{% load static i18n permission_tags %} | |
4 | - | |
5 | -{% block sidebar %} | |
6 | - <h4>{% trans 'You have:' %} </h4> | |
7 | - <div class="list-group"> | |
8 | - <a href="#" class="list-group-item"> | |
9 | - <span class="badge">4</span> | |
10 | - {% trans 'Pending Tasks' %} | |
11 | - </a> | |
12 | - <a href="#" class="list-group-item"> | |
13 | - <span class="badge">0</span> | |
14 | - {% trans 'Users Online' %} | |
15 | - </a> | |
16 | - </div> | |
17 | - | |
18 | - <hr /> | |
19 | - | |
20 | - <h4>{% trans 'You can:' %} </h4> | |
21 | - <div class="list-group"> | |
22 | - {% if user|has_role:'professor' %} | |
23 | - <a href="{% url 'course:create' %}" class="list-group-item"> | |
24 | - {% trans 'Create Course' %} | |
25 | - </a> | |
26 | - {% endif %} | |
27 | - {% if user|has_role:'professor' %} | |
28 | - <a href="{% url 'users:manage' %}" class="list-group-item"> | |
29 | - {% trans 'Manage Users' %} | |
30 | - </a> | |
31 | - {% endif %} | |
32 | - <a href="{% url 'course:manage' %}" class="list-group-item"> | |
33 | - {% trans 'Manage Courses' %} | |
34 | - </a> | |
35 | - {% if user|has_role:'professor' %} | |
36 | - <a href="{% url 'course:manage_cat' %}" class="list-group-item"> | |
37 | - {% trans 'Gerenciar Categorias' %} | |
38 | - </a> | |
39 | - {% endif %} | |
40 | - </div> | |
41 | - | |
42 | - <hr /> | |
43 | - | |
44 | - {% if user|has_role:'student' %} | |
45 | - <h4>{% trans 'Your course(s):' %}</h4> | |
46 | - <p>{% trans 'No courses subscribed yet' %}</p> | |
47 | - {% endif %} | |
48 | -{% endblock %} | |
49 | - | |
50 | -{% block content %} | |
51 | - <div class="row"> | |
52 | - <div class="col-sm-12"> | |
53 | - <form class="form-horizontal" method="post"> | |
54 | - <div class="col-sm-10"> | |
55 | - <div class="form-group"> | |
56 | - <label for="search_keyword" class="control-label col-sm-3">{% trans 'Search course:' %} </label> | |
57 | - <div class="col-sm-9"> | |
58 | - <input type="text" class="form-control input-sm" id="search_keyword" /> | |
59 | - </div> | |
60 | - </div> | |
61 | - </div> | |
62 | - <button type="submit" class="btn btn-sm btn-success">{% trans 'Search' %}</button> | |
63 | - </form> | |
64 | - | |
65 | - <hr /> | |
66 | - | |
67 | - <h5>{% trans 'Most popular keywords:' %}</h5> | |
68 | - <div class="well"> | |
69 | - <center> | |
70 | - <ul class="cloud"> | |
71 | - <li> | |
72 | - <a href=""> | |
73 | - teste amadeus prospb | |
74 | - </a> | |
75 | - </li> | |
76 | - <li> | |
77 | - <a href=""> | |
78 | - programação fácil | |
79 | - </a> | |
80 | - </li> | |
81 | - <li> | |
82 | - <a href=""> | |
83 | - intermediário | |
84 | - </a> | |
85 | - </li> | |
86 | - <li> | |
87 | - <a href=""> | |
88 | - amadeus | |
89 | - </a> | |
90 | - </li> | |
91 | - <li> | |
92 | - <a href=""> | |
93 | - palavra02 | |
94 | - </a> | |
95 | - </li> | |
96 | - <li> | |
97 | - <a href=""> | |
98 | - programação para iniciantes | |
99 | - </a> | |
100 | - </li> | |
101 | - <li> | |
102 | - <a href=""> | |
103 | - django | |
104 | - </a> | |
105 | - </li> | |
106 | - <li> | |
107 | - <a href=""> | |
108 | - aluno teste | |
109 | - </a> | |
110 | - </li> | |
111 | - <li> | |
112 | - <a href=""> | |
113 | - curso0101 | |
114 | - </a> | |
115 | - </li> | |
116 | - <li> | |
117 | - <a href=""> | |
118 | - kjsdnksa | |
119 | - </a> | |
120 | - </li> | |
121 | - <li> | |
122 | - <a href=""> | |
123 | - palavra01 | |
124 | - </a> | |
125 | - </li> | |
126 | - <li> | |
127 | - <a href=""> | |
128 | - programming | |
129 | - </a> | |
130 | - </li> | |
131 | - <li> | |
132 | - <a href=""> | |
133 | - python | |
134 | - </a> | |
135 | - </li> | |
136 | - <li> | |
137 | - <a href=""> | |
138 | - curso | |
139 | - </a> | |
140 | - </li> | |
141 | - <li> | |
142 | - <a href=""> | |
143 | - mvc | |
144 | - </a> | |
145 | - </li> | |
146 | - <li> | |
147 | - <a href=""> | |
148 | - programação web | |
149 | - </a> | |
150 | - </li> | |
151 | - <li> | |
152 | - <a href=""> | |
153 | - ionic | |
154 | - </a> | |
155 | - </li> | |
156 | - <li> | |
157 | - <a href=""> | |
158 | - framework | |
159 | - </a> | |
160 | - </li> | |
161 | - <li> | |
162 | - <a href=""> | |
163 | - web | |
164 | - </a> | |
165 | - </li> | |
166 | - <li> | |
167 | - <a href=""> | |
168 | - android | |
169 | - </a> | |
170 | - </li> | |
171 | - <li> | |
172 | - <a href=""> | |
173 | - programação | |
174 | - </a> | |
175 | - </li> | |
176 | - </ul> | |
177 | - </center> | |
178 | - </div> | |
179 | - </div> | |
180 | - </div> | |
181 | -{% endblock %} |
core/admin.py
1 | 1 | from django.contrib import admin |
2 | - | |
3 | -from .models import Action, Resource, Action_Resource, Log | |
2 | +from .models import Action, Resource, Action_Resource, Log, MimeType | |
4 | 3 | |
5 | 4 | class ActionAdmin(admin.ModelAdmin): |
6 | 5 | list_display = ['name', 'created_date'] |
... | ... | @@ -18,7 +17,12 @@ class LogAdmin(admin.ModelAdmin): |
18 | 17 | list_display = ['datetime', 'user', 'action_resource'] |
19 | 18 | search_fields = ['user'] |
20 | 19 | |
20 | +class MimeTypeAdmin(admin.ModelAdmin): | |
21 | + list_display = ['typ', 'icon'] | |
22 | + search_fields = ['typ', 'icon'] | |
23 | + | |
21 | 24 | admin.site.register(Action, ActionAdmin) |
22 | 25 | admin.site.register(Resource, ResourceAdmin) |
23 | 26 | admin.site.register(Action_Resource, ActionResourceAdmin) |
24 | -admin.site.register(Log, LogAdmin) | |
25 | 27 | \ No newline at end of file |
28 | +admin.site.register(Log, LogAdmin) | |
29 | +admin.site.register(MimeType, MimeTypeAdmin) | ... | ... |
core/decorators.py
... | ... | @@ -48,16 +48,15 @@ def log_decorator(log_action = '', log_resource = ''): |
48 | 48 | |
49 | 49 | |
50 | 50 | def notification_decorator(read = False, message = '', actor = None, users = [], not_action='', not_resource='', resource_link=''): |
51 | - | |
51 | + | |
52 | 52 | def _notification_decorator(view_function): |
53 | 53 | |
54 | 54 | def _decorator(request, *args, **kwargs): |
55 | 55 | #Do something before the call |
56 | - | |
56 | + | |
57 | 57 | response = view_function(request, *args, **kwargs) |
58 | 58 | action = Action.objects.filter(name = not_action) |
59 | 59 | resource = Resource.objects.filter(name = not_resource) |
60 | - print(resource_link) | |
61 | 60 | if action.exists(): |
62 | 61 | action = action[0] |
63 | 62 | else: |
... | ... | @@ -68,7 +67,6 @@ def notification_decorator(read = False, message = '', actor = None, users = [], |
68 | 67 | resource = resource[0] |
69 | 68 | else: |
70 | 69 | resource = Resource(name = not_resource, url= resource_link) |
71 | - print(resource) | |
72 | 70 | resource.save() |
73 | 71 | |
74 | 72 | action_resource = Action_Resource.objects.filter(action = action, resource = resource) |
... | ... | @@ -82,11 +80,11 @@ def notification_decorator(read = False, message = '', actor = None, users = [], |
82 | 80 | for user in users: |
83 | 81 | notification = Notification(user=user, actor= actor, message=message, action_resource= action_resource) |
84 | 82 | notification.save() |
85 | - | |
86 | - | |
83 | + | |
84 | + | |
87 | 85 | #Do something after the call |
88 | 86 | return response |
89 | 87 | |
90 | 88 | return wraps(view_function)(_decorator) |
91 | - | |
92 | - return _notification_decorator | |
93 | 89 | \ No newline at end of file |
90 | + | |
91 | + return _notification_decorator | ... | ... |
core/migrations/0001_initial.py
1 | 1 | # -*- coding: utf-8 -*- |
2 | -# Generated by Django 1.10 on 2016-10-05 13:37 | |
2 | +# Generated by Django 1.10 on 2016-10-18 20:26 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | 5 | import autoslug.fields |
6 | -from django.conf import settings | |
7 | 6 | from django.db import migrations, models |
8 | 7 | import django.db.models.deletion |
9 | 8 | |
... | ... | @@ -13,7 +12,6 @@ class Migration(migrations.Migration): |
13 | 12 | initial = True |
14 | 13 | |
15 | 14 | dependencies = [ |
16 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
17 | 15 | ] |
18 | 16 | |
19 | 17 | operations = [ |
... | ... | @@ -33,7 +31,6 @@ class Migration(migrations.Migration): |
33 | 31 | name='Action_Resource', |
34 | 32 | fields=[ |
35 | 33 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
36 | - ('action', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action', verbose_name='Action_Applied')), | |
37 | 34 | ], |
38 | 35 | options={ |
39 | 36 | 'verbose_name': 'Action_Resource', |
... | ... | @@ -45,8 +42,6 @@ class Migration(migrations.Migration): |
45 | 42 | fields=[ |
46 | 43 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
47 | 44 | ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), |
48 | - ('action_resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource')), | |
49 | - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Actor')), | |
50 | 45 | ], |
51 | 46 | options={ |
52 | 47 | 'verbose_name': 'Log', |
... | ... | @@ -54,6 +49,18 @@ class Migration(migrations.Migration): |
54 | 49 | }, |
55 | 50 | ), |
56 | 51 | migrations.CreateModel( |
52 | + name='MimeType', | |
53 | + fields=[ | |
54 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
55 | + ('typ', models.CharField(max_length=100, unique=True, verbose_name='Type')), | |
56 | + ('icon', models.CharField(max_length=50, unique=True, verbose_name='Icon')), | |
57 | + ], | |
58 | + options={ | |
59 | + 'verbose_name': 'Amadeus Mime Type', | |
60 | + 'verbose_name_plural': 'Amadeus Mime Types', | |
61 | + }, | |
62 | + ), | |
63 | + migrations.CreateModel( | |
57 | 64 | name='Notification', |
58 | 65 | fields=[ |
59 | 66 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
... | ... | @@ -61,8 +68,6 @@ class Migration(migrations.Migration): |
61 | 68 | ('read', models.BooleanField(default=False, verbose_name='Read')), |
62 | 69 | ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), |
63 | 70 | ('action_resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource')), |
64 | - ('actor', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_Performer', to=settings.AUTH_USER_MODEL, verbose_name='Perfomer')), | |
65 | - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notification_Actor', to=settings.AUTH_USER_MODEL, verbose_name='User')), | |
66 | 71 | ], |
67 | 72 | options={ |
68 | 73 | 'verbose_name': 'Notification', |
... | ... | @@ -83,9 +88,4 @@ class Migration(migrations.Migration): |
83 | 88 | 'verbose_name_plural': 'Resources', |
84 | 89 | }, |
85 | 90 | ), |
86 | - migrations.AddField( | |
87 | - model_name='action_resource', | |
88 | - name='resource', | |
89 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Resource', verbose_name='Resource'), | |
90 | - ), | |
91 | 91 | ] | ... | ... |
... | ... | @@ -0,0 +1,50 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Generated by Django 1.10 on 2016-10-18 20:26 | |
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='Perfomer'), | |
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_mymetype.py
... | ... | @@ -1,27 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-12 17:29 | |
3 | -from __future__ import unicode_literals | |
4 | - | |
5 | -from django.db import migrations, models | |
6 | - | |
7 | - | |
8 | -class Migration(migrations.Migration): | |
9 | - | |
10 | - dependencies = [ | |
11 | - ('core', '0001_initial'), | |
12 | - ] | |
13 | - | |
14 | - operations = [ | |
15 | - migrations.CreateModel( | |
16 | - name='MymeType', | |
17 | - fields=[ | |
18 | - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
19 | - ('typ', models.CharField(max_length=100, unique=True, verbose_name='Type')), | |
20 | - ('icon', models.CharField(max_length=50, unique=True, verbose_name='Icon')), | |
21 | - ], | |
22 | - options={ | |
23 | - 'verbose_name_plural': 'Amadeus Myme Types', | |
24 | - 'verbose_name': 'Amadeus Myme Type', | |
25 | - }, | |
26 | - ), | |
27 | - ] |
core/mixins.py
... | ... | @@ -47,7 +47,6 @@ class NotificationMixin(object): |
47 | 47 | def createNotification(self, message='', actor=None, users = User.objects.all(), resource_slug='' ,action_name = '', resource_name='', resource_link=''): #the default will be a broadcast |
48 | 48 | action = Action.objects.filter(name = action_name) |
49 | 49 | resource = Resource.objects.filter(slug = resource_slug) |
50 | - print(message) | |
51 | 50 | if action.exists(): |
52 | 51 | action = action[0] |
53 | 52 | else: |
... | ... | @@ -76,5 +75,4 @@ class NotificationMixin(object): |
76 | 75 | def dispatch(self, request, *args, **kwargs): |
77 | 76 | """ |
78 | 77 | Not quite sure how to do about it""" |
79 | - print("testing IF IT REACHES HERE") | |
80 | - return super(NotificationMixin, self).dispatch(request, *args, **kwargs) | |
81 | 78 | \ No newline at end of file |
79 | + return super(NotificationMixin, self).dispatch(request, *args, **kwargs) | ... | ... |
core/models.py
... | ... | @@ -4,13 +4,13 @@ from users.models import User |
4 | 4 | from autoslug.fields import AutoSlugField |
5 | 5 | # Create your models here. |
6 | 6 | |
7 | -class MymeType(models.Model): | |
7 | +class MimeType(models.Model): | |
8 | 8 | typ = models.CharField(_('Type'), max_length=100, unique=True) |
9 | 9 | icon = models.CharField(_('Icon'), max_length=50, unique=True) |
10 | 10 | |
11 | 11 | class Meta: |
12 | - verbose_name= _('Amadeus Myme Type') | |
13 | - verbose_name_plural = _('Amadeus Myme Types') | |
12 | + verbose_name= _('Amadeus Mime Type') | |
13 | + verbose_name_plural = _('Amadeus Mime Types') | |
14 | 14 | |
15 | 15 | def get_icon(self, type): |
16 | 16 | pass | ... | ... |
... | ... | @@ -0,0 +1,315 @@ |
1 | +.navbar .logo {position: absolute; top: 6px; text-align: center; height: 48px; width: 48px;} | |
2 | + | |
3 | +/* Modal */ | |
4 | +.modal-header {min-height: 60px; border-bottom: 1px solid #E6E7E8 !important; padding-bottom: 15px !important;} | |
5 | +.modal-footer {text-align: right; padding-top: 5px !important; border-top: 1px solid #E6E7E8 !important;} | |
6 | + | |
7 | +/* HEADER */ | |
8 | +#notification-dropdown{ | |
9 | + max-height: 500%; | |
10 | + overflow: auto; | |
11 | + width: 200px; | |
12 | +} | |
13 | + | |
14 | +/* HEADER */ | |
15 | + | |
16 | + | |
17 | +.logoLogin{ | |
18 | + padding-bottom: 1%; | |
19 | + width: 15%; | |
20 | +} | |
21 | +.navigation{ | |
22 | + margin: 10% 10% 5% 5%; | |
23 | +} | |
24 | +.breadcrumb{ | |
25 | + margin-bottom: 5px; | |
26 | +} | |
27 | +.courseHome{ | |
28 | + text-align: center; | |
29 | +} | |
30 | +.courseHome ul{ | |
31 | + list-style-type: none; | |
32 | + margin: 0; | |
33 | + padding: 0; | |
34 | + overflow: hidden; | |
35 | + margin-left: 2%; | |
36 | +} | |
37 | +.courseHome ul li{ | |
38 | + display:inline; | |
39 | + text-align: center; | |
40 | + padding: 16px; | |
41 | +} | |
42 | +.goal{ | |
43 | + margin: 0%; | |
44 | + margin-top: 10%; | |
45 | + padding-bottom: 200px; | |
46 | +} | |
47 | +.favorites{ | |
48 | + margin: 0%; | |
49 | + margin-top: 20%; | |
50 | + padding-bottom: 200px; | |
51 | +} | |
52 | +.panel-info{ | |
53 | +} | |
54 | +.panel-default{ | |
55 | +} | |
56 | +.panel-primary .panel-body{ | |
57 | + padding: 0% 0% 0% 0%; | |
58 | +} | |
59 | +.end{ | |
60 | + text-align: right; | |
61 | +} | |
62 | +h5{ | |
63 | + text-align: center; | |
64 | +} | |
65 | +#img { | |
66 | + | |
67 | + display: block; | |
68 | + margin: auto; | |
69 | + width: 50%; | |
70 | + | |
71 | +} | |
72 | +ul { | |
73 | + list-style-type:none | |
74 | +} | |
75 | + | |
76 | + | |
77 | +/*CSS TIMELINE*/ | |
78 | + | |
79 | +.panel-title{ /*Because we use an outer a tag*/ | |
80 | + color: rgba(255,255,255,.84); | |
81 | +} | |
82 | + | |
83 | +.bubble { | |
84 | + width: 100%; | |
85 | + padding: .5em 1em; | |
86 | + line-height: 1.4em; | |
87 | + padding: 20px; | |
88 | + background-color: #ecf0f1; | |
89 | + position: relative; | |
90 | + -webkit-border-radius: 8px; | |
91 | + -moz-border-radius: 8px; | |
92 | + -ms-border-radius: 8px; | |
93 | + -o-border-radius: 8px; | |
94 | + border-radius: 8px; | |
95 | + text-align: left; | |
96 | + display: inline-block; } | |
97 | + .bubble:hover > .over-bubble { | |
98 | + opacity: 1; } | |
99 | + | |
100 | +.bubble-container { | |
101 | + width: 75%; | |
102 | + display: block; | |
103 | + position: relative; | |
104 | + padding-left: 20px; | |
105 | + vertical-align: top; | |
106 | + display: inline-block; } | |
107 | + | |
108 | +.arrow { | |
109 | + content: ''; | |
110 | + display: block; | |
111 | + position: absolute; | |
112 | + left: 12px; | |
113 | + bottom: 25%; | |
114 | + height: 0; | |
115 | + width: 0; | |
116 | + border-top: 20px solid transparent; | |
117 | + border-bottom: 20px solid transparent; | |
118 | + border-right: 20px solid #ecf0f1; } | |
119 | + | |
120 | +.timeline { | |
121 | + width: 560px; | |
122 | + display: block; | |
123 | + margin: auto; | |
124 | + background-color: #dde1e2; | |
125 | + padding-bottom: 2em; | |
126 | + -webkit-box-shadow: #bdc3c7 0 5px 5px; | |
127 | + -moz-box-shadow: #bdc3c7 0 5px 5px; | |
128 | + box-shadow: #bdc3c7 0 5px 5px; | |
129 | + -moz-border-radius-bottomleft: 8px; | |
130 | + -webkit-border-bottom-left-radius: 8px; | |
131 | + border-bottom-left-radius: 8px; | |
132 | + -moz-border-radius-bottomright: 8px; | |
133 | + -webkit-border-bottom-right-radius: 8px; | |
134 | + border-bottom-right-radius: 8px; | |
135 | + margin-bottom: 2em; } | |
136 | + .timeline li { | |
137 | + padding: 1em 0; } | |
138 | + .timeline li.not_read { | |
139 | + background-color: #d3d7d8; } | |
140 | + | |
141 | +.avatar { | |
142 | + width: 18%; | |
143 | + display: inline-block; | |
144 | + vertical-align: top; | |
145 | + position: relative; | |
146 | + overflow: hidden; | |
147 | + margin-left: 2%; } | |
148 | + .avatar img { | |
149 | + width: 100%; | |
150 | + -webkit-border-radius: 50%; | |
151 | + -moz-border-radius: 50%; | |
152 | + -ms-border-radius: 50%; | |
153 | + -o-border-radius: 50%; | |
154 | + border-radius: 50%; | |
155 | + border: 5px solid #ecf0f1; | |
156 | + position: relative; } | |
157 | + | |
158 | + | |
159 | + | |
160 | +.first { | |
161 | + width: 560px; | |
162 | + display: block; | |
163 | + margin: auto; | |
164 | + background-color: #3498db; | |
165 | + text-shadow: #2084c7 1px 1px 0; | |
166 | + padding: 1em 0 !important; | |
167 | + color: white; | |
168 | + text-align: center; | |
169 | + margin-top: 1em; | |
170 | + font-family: "Lato"; | |
171 | + font-size: 1.6em; | |
172 | + -moz-border-radius-topleft: 8px; | |
173 | + -webkit-border-top-left-radius: 8px; | |
174 | + border-top-left-radius: 8px; | |
175 | + -moz-border-radius-topright: 8px; | |
176 | + -webkit-border-top-right-radius: 8px; | |
177 | + border-top-right-radius: 8px; | |
178 | + position: relative; } | |
179 | + | |
180 | + | |
181 | +.over-bubble { | |
182 | + line-height: 1.4em; | |
183 | + padding-top: 10%; | |
184 | + background-color: rgba(236, 240, 241, 0.8); | |
185 | + position: relative; | |
186 | + -webkit-border-radius: 8px; | |
187 | + -moz-border-radius: 8px; | |
188 | + -ms-border-radius: 8px; | |
189 | + -o-border-radius: 8px; | |
190 | + border-radius: 8px; | |
191 | + text-align: center; | |
192 | + display: inline-block; | |
193 | + position: absolute !important; | |
194 | + height: 100%; | |
195 | + width: 100%; | |
196 | + opacity: 0; | |
197 | + top: 0; | |
198 | + left: 0; | |
199 | + z-index: 999; | |
200 | + -webkit-transition-property: all; | |
201 | + -moz-transition-property: all; | |
202 | + -o-transition-property: all; | |
203 | + transition-property: all; | |
204 | + -webkit-transition-duration: 0.3s; | |
205 | + -moz-transition-duration: 0.3s; | |
206 | + -o-transition-duration: 0.3s; | |
207 | + transition-duration: 0.3s; | |
208 | + -webkit-transition-timing-function: ease-in; | |
209 | + -moz-transition-timing-function: ease-in; | |
210 | + -o-transition-timing-function: ease-in; | |
211 | + transition-timing-function: ease-in; | |
212 | + font-size: 2.8em; | |
213 | + text-shadow: white 1px 1px 0; } | |
214 | + | |
215 | +.action { | |
216 | + margin-right: .3em; | |
217 | + -webkit-transition-property: all; | |
218 | + -moz-transition-property: all; | |
219 | + -o-transition-property: all; | |
220 | + transition-property: all; | |
221 | + -webkit-transition-duration: 0.2s; | |
222 | + -moz-transition-duration: 0.2s; | |
223 | + -o-transition-duration: 0.2s; | |
224 | + transition-duration: 0.2s; | |
225 | + -webkit-transition-timing-function: ease-in; | |
226 | + -moz-transition-timing-function: ease-in; | |
227 | + -o-transition-timing-function: ease-in; | |
228 | + transition-timing-function: ease-in; } | |
229 | + | |
230 | + | |
231 | + | |
232 | +.icon-more-horiz {margin-top: 0px; margin-bottom: 0px; padding-left: 0px;} | |
233 | + | |
234 | +.retweet { | |
235 | + position: absolute; | |
236 | + opacity: 1; | |
237 | + top: 0; | |
238 | + right: 1em; | |
239 | + display: block; | |
240 | + background-color: #16a085; | |
241 | + padding: 4px; | |
242 | + -moz-border-radius-bottomleft: 5px; | |
243 | + -webkit-border-bottom-left-radius: 5px; | |
244 | + border-bottom-left-radius: 5px; | |
245 | + -moz-border-radius-bottomright: 5px; | |
246 | + -webkit-border-bottom-right-radius: 5px; | |
247 | + border-bottom-right-radius: 5px; } | |
248 | + .retweet .icon-retweet { | |
249 | + color: white; | |
250 | + margin: auto; | |
251 | + width: 100%; | |
252 | + display: block; | |
253 | + font-size: 1.2em; } | |
254 | + | |
255 | +/*CSS NOTIFICACIONS*/ | |
256 | + | |
257 | +.alert_list{font-size: 11px; color:grey} | |
258 | +li.alert_li { | |
259 | + font-size: 11px; | |
260 | + color:grey; | |
261 | + padding:10px 0px 2px 0px; | |
262 | + border-bottom: thin solid #c0c0c0; | |
263 | +} | |
264 | +li.alert_li:hover{background-color:#eee} | |
265 | +.turn_off_alert{float:right;margin-bottom :1px} | |
266 | +a.alert_message{color : grey} | |
267 | +a.alert_message:hover{color : grey} | |
268 | + | |
269 | +/*=================== Ailson - Please Don't touch*/ | |
270 | +.breadcrumb .divider{ | |
271 | + display: none; | |
272 | +} | |
273 | + | |
274 | +.accordion { | |
275 | + background: #c0c0c0; | |
276 | +} | |
277 | +.accordion_list { | |
278 | + background: #e0e0e0; | |
279 | +} | |
280 | + | |
281 | +body .container .jumbotron-inverse, body .container .well-inverse, body .container-fluid .jumbotron-inverse, body .container-fluid .well-inverse { | |
282 | + background-color: white; | |
283 | +} | |
284 | +.forum_collapse { | |
285 | + color: #000; | |
286 | +} | |
287 | +.forum_collapse:hover, .forum_collapse:focus { | |
288 | + text-decoration: none; | |
289 | + color: #000; | |
290 | +} | |
291 | + | |
292 | +.timeline.post { | |
293 | + border-top-left-radius: 8px; | |
294 | + border-top-right-radius: 8px; | |
295 | + padding-bottom: 0px; | |
296 | + -webkit-padding-start: 0px !important; | |
297 | + width: 100%; | |
298 | +} | |
299 | +.timeline.post a { | |
300 | + color: #000; | |
301 | +} | |
302 | +.timeline.post li { | |
303 | + padding: 10px; | |
304 | + border-bottom: 1px solid #fff; | |
305 | +} | |
306 | +.timeline.post li:last-child { | |
307 | + border: none; | |
308 | +} | |
309 | +.timeline.post h3 { | |
310 | + margin-top: 5px; | |
311 | +} | |
312 | + | |
313 | +.notification-count { | |
314 | + background-color: #FF0000; | |
315 | +} | ... | ... |
core/static/css/base/amadeus.css
core/templates/base.html
... | ... | @@ -116,6 +116,9 @@ |
116 | 116 | </div> |
117 | 117 | <script src="{% static 'js/main.js' %}"></script> |
118 | 118 | <script type="text/javascript" src="{% static 'js/topic_editation_presentation.js' %}"></script> |
119 | + {% block script_file %} | |
120 | + | |
121 | + {% endblock script_file %} | |
119 | 122 | </body> |
120 | 123 | |
121 | 124 | </html> | ... | ... |
core/templates/registration/passwor_reset_complete.html
... | ... | @@ -22,9 +22,7 @@ |
22 | 22 | <form class="form-group " method="post" action=""> |
23 | 23 | {% csrf_token %} |
24 | 24 | <div class="form-group is-empty"> |
25 | - <p> | |
26 | - Sua senha foi definida. Você pode ir em frente e entrar agora. | |
27 | - </p> | |
25 | + <p>{% trans "Your password has been set. You can go ahead and go now." %}</p> | |
28 | 26 | </div> |
29 | 27 | </form> |
30 | 28 | </div> | ... | ... |
core/templates/registration/passwor_reset_done.html
... | ... | @@ -22,14 +22,8 @@ |
22 | 22 | <form class="form-group " method="post" action=""> |
23 | 23 | {% csrf_token %} |
24 | 24 | <div class="form-group is-empty"> |
25 | - <p> | |
26 | - Temos enviado instruções para configurar sua senha, se uma conta existe com o e-mail inserido. | |
27 | - Você deve recebê-los em breve. | |
28 | - </p> | |
29 | - <p> | |
30 | - Se você não receber um e-mail, por favor, certifique-se de que introduziu o endereço que você registrou, | |
31 | - e verifique a pasta de spam. | |
32 | - </p> | |
25 | + <p>{% trans "We have sent instructions to set up your password, if an account exists with the email entered. You should receive them soon." %}</p> | |
26 | + <p>{% trans "If you do not receive an email, please make sure you entered the address you registered, and check the spam folder." %}</p> | |
33 | 27 | </div> |
34 | 28 | </form> |
35 | 29 | </div> | ... | ... |
core/views.py
... | ... | @@ -102,7 +102,7 @@ def processNotification(self, notificationId): |
102 | 102 | def getNotifications(request): |
103 | 103 | context = {} |
104 | 104 | if request.user.is_authenticated: |
105 | - | |
105 | + | |
106 | 106 | steps = int(request.GET['steps']) |
107 | 107 | amount = int(request.GET['amount']) |
108 | 108 | notifications = Notification.objects.filter(user= request.user, read=False).order_by('-datetime')[steps:steps+amount] |
... | ... | @@ -110,18 +110,6 @@ def getNotifications(request): |
110 | 110 | else: #go to login page |
111 | 111 | return HttpResponse('teste') |
112 | 112 | |
113 | - | |
113 | + | |
114 | 114 | html = render_to_string("notifications.html", context) |
115 | - print(html) | |
116 | 115 | return HttpResponse(html) |
117 | - | |
118 | - | |
119 | - | |
120 | - | |
121 | -# class LoginClass(LoginView): | |
122 | -# template_name='index.html' | |
123 | -# | |
124 | -# def get_context_data(self, **kwargs): | |
125 | -# context = super(LoginClass,self).get_context_data(**kwargs) | |
126 | -# print ("deu certo") | |
127 | -# return context | ... | ... |
courses/admin.py
1 | 1 | from django.contrib import admin |
2 | 2 | |
3 | -from .models import CourseCategory, Course, Subject,Topic, Activity, Material | |
3 | +from .models import CourseCategory, Course, Subject,Topic, Activity, Material, CategorySubject | |
4 | 4 | |
5 | 5 | class CategoryAdmin(admin.ModelAdmin): |
6 | 6 | list_display = ['name', 'slug'] |
7 | 7 | search_fields = ['name', 'slug'] |
8 | 8 | |
9 | +class CategorySubjectAdmin(admin.ModelAdmin): | |
10 | + list_display = ['name', 'slug'] | |
11 | + search_fields = ['name', 'slug'] | |
12 | + | |
9 | 13 | class CourseAdmin(admin.ModelAdmin): |
10 | 14 | list_display = ['name', 'slug'] |
11 | 15 | search_fields = ['name', 'slug'] |
... | ... | @@ -32,3 +36,4 @@ admin.site.register(Subject, SubjectAdmin) |
32 | 36 | admin.site.register(Topic, TopicAdmin) |
33 | 37 | admin.site.register(Activity,ActivityAdmin) |
34 | 38 | admin.site.register(Material,MaterialAdmin) |
39 | +admin.site.register(CategorySubject, CategorySubjectAdmin) | ... | ... |
courses/forms.py
1 | 1 | from django import forms |
2 | 2 | from django.utils.translation import ugettext_lazy as _ |
3 | -from .models import CourseCategory, Course, Subject, Topic, ActivityFile, Activity | |
3 | +from .models import CourseCategory, Course, Subject, Topic, ActivityFile, Activity, FileMaterial, LinkMaterial | |
4 | 4 | from s3direct.widgets import S3DirectWidget |
5 | 5 | |
6 | 6 | |
... | ... | @@ -128,15 +128,19 @@ class SubjectForm(forms.ModelForm): |
128 | 128 | |
129 | 129 | class Meta: |
130 | 130 | model = Subject |
131 | - fields = ('name', 'description', 'visible',) | |
131 | + fields = ('name', 'description','init_date', 'end_date', 'visible',) | |
132 | 132 | labels = { |
133 | 133 | 'name': _('Name'), |
134 | 134 | 'description': _('Description'), |
135 | + 'init_date': _('Start date'), | |
136 | + 'end_date': _('End date'), | |
135 | 137 | 'visible': _('Is it visible?'), |
136 | 138 | } |
137 | 139 | help_texts = { |
138 | 140 | 'name': _("Subjects's name"), |
139 | 141 | 'description': _("Subjects's description"), |
142 | + 'init_date': _('Start date of the subject'), | |
143 | + 'end_date': _('End date of the subject'), | |
140 | 144 | 'visible': _('Is the subject visible?'), |
141 | 145 | } |
142 | 146 | |
... | ... | @@ -184,7 +188,17 @@ class ActivityFileForm(forms.ModelForm): |
184 | 188 | model = ActivityFile |
185 | 189 | fields = ['pdf','name'] |
186 | 190 | |
187 | -class ActivityForm(forms.ModelForm): | |
191 | +class ActivityForm(forms.ModelForm): | |
188 | 192 | class Meta: |
189 | 193 | model = Activity |
190 | 194 | fields = ['topic', 'limit_date', 'students','all_students'] |
195 | + | |
196 | +class FileMaterialForm(forms.ModelForm): | |
197 | + class Meta: | |
198 | + model = FileMaterial | |
199 | + fields = ['name', 'file'] | |
200 | + | |
201 | +class LinkMaterialForm(forms.ModelForm): | |
202 | + class Meta: | |
203 | + model = LinkMaterial | |
204 | + fields = ['material', 'name', 'description','url'] | ... | ... |
courses/migrations/0001_initial.py
1 | 1 | # -*- coding: utf-8 -*- |
2 | -# Generated by Django 1.10 on 2016-10-05 13:37 | |
2 | +# Generated by Django 1.10 on 2016-10-18 20:26 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | 5 | import autoslug.fields |
6 | -from django.conf import settings | |
7 | 6 | from django.db import migrations, models |
8 | 7 | import django.db.models.deletion |
9 | 8 | import s3direct.fields |
... | ... | @@ -14,7 +13,6 @@ class Migration(migrations.Migration): |
14 | 13 | initial = True |
15 | 14 | |
16 | 15 | dependencies = [ |
17 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
18 | 16 | ('core', '0001_initial'), |
19 | 17 | ] |
20 | 18 | |
... | ... | @@ -23,9 +21,8 @@ class Migration(migrations.Migration): |
23 | 21 | name='Activity', |
24 | 22 | fields=[ |
25 | 23 | ('resource_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.Resource')), |
26 | - ('limit_date', models.DateTimeField(verbose_name='Deliver Date')), | |
24 | + ('limit_date', models.DateField(verbose_name='Deliver Date')), | |
27 | 25 | ('all_students', models.BooleanField(default=False, verbose_name='All Students')), |
28 | - ('students', models.ManyToManyField(related_name='activities', to=settings.AUTH_USER_MODEL, verbose_name='Students')), | |
29 | 26 | ], |
30 | 27 | bases=('core.resource',), |
31 | 28 | ), |
... | ... | @@ -35,7 +32,6 @@ class Migration(migrations.Migration): |
35 | 32 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
36 | 33 | ('pdf', s3direct.fields.S3DirectField()), |
37 | 34 | ('name', models.CharField(max_length=100)), |
38 | - ('diet', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='courses.Activity')), | |
39 | 35 | ], |
40 | 36 | options={ |
41 | 37 | 'verbose_name': 'Activity File', |
... | ... | @@ -43,7 +39,7 @@ class Migration(migrations.Migration): |
43 | 39 | }, |
44 | 40 | ), |
45 | 41 | migrations.CreateModel( |
46 | - name='Category', | |
42 | + name='CategorySubject', | |
47 | 43 | fields=[ |
48 | 44 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
49 | 45 | ('name', models.CharField(max_length=100, unique=True, verbose_name='Name')), |
... | ... | @@ -70,22 +66,48 @@ class Migration(migrations.Migration): |
70 | 66 | ('init_date', models.DateField(verbose_name='Begin of Course Date')), |
71 | 67 | ('end_date', models.DateField(verbose_name='End of Course Date')), |
72 | 68 | ('image', models.ImageField(blank=True, upload_to='courses/', verbose_name='Image')), |
73 | - ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Category', verbose_name='Category')), | |
74 | - ('professors', models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors')), | |
75 | - ('students', models.ManyToManyField(related_name='courses_student', to=settings.AUTH_USER_MODEL, verbose_name='Students')), | |
76 | 69 | ], |
77 | 70 | options={ |
78 | 71 | 'verbose_name': 'Course', |
79 | - 'ordering': ('create_date', 'name'), | |
80 | 72 | 'verbose_name_plural': 'Courses', |
73 | + 'ordering': ('create_date', 'name'), | |
74 | + }, | |
75 | + ), | |
76 | + migrations.CreateModel( | |
77 | + name='CourseCategory', | |
78 | + fields=[ | |
79 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
80 | + ('name', models.CharField(max_length=100, unique=True, verbose_name='Name')), | |
81 | + ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')), | |
82 | + ('create_date', models.DateField(auto_now_add=True, verbose_name='Creation Date')), | |
83 | + ], | |
84 | + options={ | |
85 | + 'verbose_name': 'Category', | |
86 | + 'verbose_name_plural': 'Categories', | |
81 | 87 | }, |
82 | 88 | ), |
83 | 89 | migrations.CreateModel( |
90 | + name='FileMaterial', | |
91 | + fields=[ | |
92 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
93 | + ('file', models.FileField(upload_to='uploads/%Y/%m/%d')), | |
94 | + ('name', models.CharField(max_length=100)), | |
95 | + ], | |
96 | + ), | |
97 | + migrations.CreateModel( | |
98 | + name='LinkMaterial', | |
99 | + fields=[ | |
100 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
101 | + ('name', models.CharField(max_length=100)), | |
102 | + ('description', models.TextField()), | |
103 | + ('url', models.URLField(max_length=300, verbose_name='Link')), | |
104 | + ], | |
105 | + ), | |
106 | + migrations.CreateModel( | |
84 | 107 | name='Material', |
85 | 108 | fields=[ |
86 | 109 | ('resource_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.Resource')), |
87 | 110 | ('all_students', models.BooleanField(default=False, verbose_name='All Students')), |
88 | - ('students', models.ManyToManyField(related_name='materials', to=settings.AUTH_USER_MODEL, verbose_name='Students')), | |
89 | 111 | ], |
90 | 112 | bases=('core.resource',), |
91 | 113 | ), |
... | ... | @@ -101,13 +123,11 @@ class Migration(migrations.Migration): |
101 | 123 | ('end_date', models.DateField(verbose_name='End of Subject Date')), |
102 | 124 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), |
103 | 125 | ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), |
104 | - ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subjects', to='courses.Course', verbose_name='Course')), | |
105 | - ('professors', models.ManyToManyField(related_name='subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors')), | |
106 | 126 | ], |
107 | 127 | options={ |
108 | 128 | 'verbose_name': 'Subject', |
109 | - 'ordering': ('create_date', 'name'), | |
110 | 129 | 'verbose_name_plural': 'Subjects', |
130 | + 'ordering': ('create_date', 'name'), | |
111 | 131 | }, |
112 | 132 | ), |
113 | 133 | migrations.CreateModel( |
... | ... | @@ -117,7 +137,6 @@ class Migration(migrations.Migration): |
117 | 137 | ('name', models.CharField(max_length=100, verbose_name='Name')), |
118 | 138 | ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')), |
119 | 139 | ('description', models.TextField(blank=True, verbose_name='Description')), |
120 | - ('subjects', models.ManyToManyField(to='courses.Subject')), | |
121 | 140 | ], |
122 | 141 | options={ |
123 | 142 | 'verbose_name': 'subject category', |
... | ... | @@ -134,23 +153,11 @@ class Migration(migrations.Migration): |
134 | 153 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), |
135 | 154 | ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), |
136 | 155 | ('visible', models.BooleanField(default=False, verbose_name='Visible')), |
137 | - ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Owner')), | |
138 | - ('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Subject', verbose_name='Subject')), | |
139 | 156 | ], |
140 | 157 | options={ |
141 | 158 | 'verbose_name': 'Topic', |
142 | - 'ordering': ('create_date', 'name'), | |
143 | 159 | 'verbose_name_plural': 'Topics', |
160 | + 'ordering': ('create_date', 'name'), | |
144 | 161 | }, |
145 | 162 | ), |
146 | - migrations.AddField( | |
147 | - model_name='material', | |
148 | - name='topic', | |
149 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='courses.Topic', verbose_name='Topic'), | |
150 | - ), | |
151 | - migrations.AddField( | |
152 | - model_name='activity', | |
153 | - name='topic', | |
154 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='courses.Topic', verbose_name='Topic'), | |
155 | - ), | |
156 | 163 | ] | ... | ... |
... | ... | @@ -0,0 +1,105 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Generated by Django 1.10 on 2016-10-18 20:26 | |
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 | + ('courses', '0001_initial'), | |
16 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
17 | + ] | |
18 | + | |
19 | + operations = [ | |
20 | + migrations.AddField( | |
21 | + model_name='topic', | |
22 | + name='owner', | |
23 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Owner'), | |
24 | + ), | |
25 | + migrations.AddField( | |
26 | + model_name='topic', | |
27 | + name='subject', | |
28 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Subject', verbose_name='Subject'), | |
29 | + ), | |
30 | + migrations.AddField( | |
31 | + model_name='subjectcategory', | |
32 | + name='subjects', | |
33 | + field=models.ManyToManyField(to='courses.Subject'), | |
34 | + ), | |
35 | + migrations.AddField( | |
36 | + model_name='subject', | |
37 | + name='category', | |
38 | + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subject_category', to='courses.CategorySubject', verbose_name='Category'), | |
39 | + ), | |
40 | + migrations.AddField( | |
41 | + model_name='subject', | |
42 | + name='course', | |
43 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subjects', to='courses.Course', verbose_name='Course'), | |
44 | + ), | |
45 | + migrations.AddField( | |
46 | + model_name='subject', | |
47 | + name='professors', | |
48 | + field=models.ManyToManyField(related_name='professors_subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors'), | |
49 | + ), | |
50 | + migrations.AddField( | |
51 | + model_name='subject', | |
52 | + name='students', | |
53 | + field=models.ManyToManyField(related_name='subject_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
54 | + ), | |
55 | + migrations.AddField( | |
56 | + model_name='material', | |
57 | + name='students', | |
58 | + field=models.ManyToManyField(related_name='materials', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
59 | + ), | |
60 | + migrations.AddField( | |
61 | + model_name='material', | |
62 | + name='topic', | |
63 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='courses.Topic', verbose_name='Topic'), | |
64 | + ), | |
65 | + migrations.AddField( | |
66 | + model_name='linkmaterial', | |
67 | + name='material', | |
68 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_link', to='courses.Material', verbose_name='Material'), | |
69 | + ), | |
70 | + migrations.AddField( | |
71 | + model_name='filematerial', | |
72 | + name='material', | |
73 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_file', to='courses.Material', verbose_name='Material'), | |
74 | + ), | |
75 | + migrations.AddField( | |
76 | + model_name='course', | |
77 | + name='category', | |
78 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_category', to='courses.CourseCategory', verbose_name='Category'), | |
79 | + ), | |
80 | + migrations.AddField( | |
81 | + model_name='course', | |
82 | + name='professors', | |
83 | + field=models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors'), | |
84 | + ), | |
85 | + migrations.AddField( | |
86 | + model_name='course', | |
87 | + name='students', | |
88 | + field=models.ManyToManyField(related_name='courses_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
89 | + ), | |
90 | + migrations.AddField( | |
91 | + model_name='activityfile', | |
92 | + name='diet', | |
93 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='courses.Activity'), | |
94 | + ), | |
95 | + migrations.AddField( | |
96 | + model_name='activity', | |
97 | + name='students', | |
98 | + field=models.ManyToManyField(related_name='activities', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
99 | + ), | |
100 | + migrations.AddField( | |
101 | + model_name='activity', | |
102 | + name='topic', | |
103 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='courses.Topic', verbose_name='Topic'), | |
104 | + ), | |
105 | + ] | ... | ... |
courses/migrations/0002_subject_students.py
... | ... | @@ -1,22 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-05 21:02 | |
3 | -from __future__ import unicode_literals | |
4 | - | |
5 | -from django.conf import settings | |
6 | -from django.db import migrations, models | |
7 | - | |
8 | - | |
9 | -class Migration(migrations.Migration): | |
10 | - | |
11 | - dependencies = [ | |
12 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
13 | - ('courses', '0001_initial'), | |
14 | - ] | |
15 | - | |
16 | - operations = [ | |
17 | - migrations.AddField( | |
18 | - model_name='subject', | |
19 | - name='students', | |
20 | - field=models.ManyToManyField(related_name='subject_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
21 | - ), | |
22 | - ] |
courses/migrations/0003_auto_20161007_1612.py
... | ... | @@ -1,30 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-07 19:12 | |
3 | -from __future__ import unicode_literals | |
4 | - | |
5 | -from django.conf import settings | |
6 | -from django.db import migrations, models | |
7 | - | |
8 | - | |
9 | -class Migration(migrations.Migration): | |
10 | - | |
11 | - dependencies = [ | |
12 | - ('courses', '0002_subject_students'), | |
13 | - ] | |
14 | - | |
15 | - operations = [ | |
16 | - migrations.RenameModel( | |
17 | - old_name='Category', | |
18 | - new_name='CourseCategory', | |
19 | - ), | |
20 | - migrations.AlterField( | |
21 | - model_name='activity', | |
22 | - name='limit_date', | |
23 | - field=models.DateField(verbose_name='Deliver Date'), | |
24 | - ), | |
25 | - migrations.AlterField( | |
26 | - model_name='subject', | |
27 | - name='professors', | |
28 | - field=models.ManyToManyField(related_name='professors_subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors'), | |
29 | - ), | |
30 | - ] |
courses/migrations/0004_auto_20161011_1951.py
... | ... | @@ -1,21 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-11 22:51 | |
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 | - ('courses', '0003_auto_20161007_1612'), | |
13 | - ] | |
14 | - | |
15 | - operations = [ | |
16 | - migrations.AlterField( | |
17 | - model_name='course', | |
18 | - name='category', | |
19 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_category', to='courses.CourseCategory', verbose_name='Category'), | |
20 | - ), | |
21 | - ] |
courses/migrations/0005_file.py
... | ... | @@ -1,31 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-13 17:29 | |
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 | - ('core', '0002_mymetype'), | |
13 | - ('courses', '0004_auto_20161011_1951'), | |
14 | - ] | |
15 | - | |
16 | - operations = [ | |
17 | - migrations.CreateModel( | |
18 | - name='File', | |
19 | - fields=[ | |
20 | - ('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')), | |
21 | - ('description', models.TextField(blank=True, verbose_name='Description')), | |
22 | - ('content', models.FileField(upload_to='uploads/courses/subject/topic/%Y/%m/%d/')), | |
23 | - ('typ', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='file', to='core.MymeType', verbose_name='Type')), | |
24 | - ], | |
25 | - options={ | |
26 | - 'verbose_name': 'Topic file', | |
27 | - 'verbose_name_plural': 'Topic files', | |
28 | - }, | |
29 | - bases=('courses.material',), | |
30 | - ), | |
31 | - ] |
courses/models.py
... | ... | @@ -2,7 +2,7 @@ from django.utils.translation import ugettext_lazy as _ |
2 | 2 | from django.db import models |
3 | 3 | from autoslug.fields import AutoSlugField |
4 | 4 | from users.models import User |
5 | -from core.models import Resource, MymeType | |
5 | +from core.models import Resource, MimeType | |
6 | 6 | from s3direct.fields import S3DirectField |
7 | 7 | |
8 | 8 | class CourseCategory(models.Model): |
... | ... | @@ -18,6 +18,18 @@ class CourseCategory(models.Model): |
18 | 18 | def __str__(self): |
19 | 19 | return self.name |
20 | 20 | |
21 | +class CategorySubject(models.Model): | |
22 | + name = models.CharField(_('Name'), max_length=100, unique=True) | |
23 | + slug = AutoSlugField(_("Slug"), populate_from='name', unique=True) | |
24 | + create_date = models.DateField(_('Creation Date'), auto_now_add=True) | |
25 | + | |
26 | + class Meta: | |
27 | + verbose_name = _('Category') | |
28 | + verbose_name_plural = _('Categories') | |
29 | + | |
30 | + def __str__(self): | |
31 | + return self.name | |
32 | + | |
21 | 33 | class Course(models.Model): |
22 | 34 | |
23 | 35 | name = models.CharField(_('Name'), max_length = 100) |
... | ... | @@ -54,6 +66,7 @@ class Subject(models.Model): |
54 | 66 | create_date = models.DateTimeField(_('Creation Date'), auto_now_add = True) |
55 | 67 | update_date = models.DateTimeField(_('Date of last update'), auto_now=True) |
56 | 68 | course = models.ForeignKey(Course, verbose_name = _('Course'), related_name="subjects") |
69 | + category = models.ForeignKey(CategorySubject, verbose_name = _('Category'), related_name='subject_category',null=True) | |
57 | 70 | professors = models.ManyToManyField(User,verbose_name=_('Professors'), related_name='professors_subjects') |
58 | 71 | students = models.ManyToManyField(User,verbose_name=_('Students'), related_name='subject_student') |
59 | 72 | |
... | ... | @@ -114,6 +127,17 @@ class Material(Resource): |
114 | 127 | topic = models.ForeignKey(Topic, verbose_name = _('Topic'), related_name='materials') |
115 | 128 | students = models.ManyToManyField(User, verbose_name = _('Students'), related_name='materials') |
116 | 129 | all_students = models.BooleanField(_('All Students'), default=False) |
130 | + | |
131 | +class FileMaterial(models.Model): | |
132 | + material = models.ForeignKey(Material, verbose_name = _('Material'), related_name='material_file') | |
133 | + file = models.FileField(upload_to='uploads/%Y/%m/%d') | |
134 | + name = models.CharField(max_length=100) | |
135 | + | |
136 | +class LinkMaterial(models.Model): | |
137 | + material = models.ForeignKey(Material, verbose_name = _('Material'), related_name='material_link') | |
138 | + name = models.CharField(max_length=100) | |
139 | + description = models.TextField() | |
140 | + url = models.URLField('Link', max_length=300) | |
117 | 141 | |
118 | 142 | """ |
119 | 143 | It is a category for each subject. | ... | ... |
... | ... | @@ -0,0 +1,82 @@ |
1 | +function getCookie(name) { | |
2 | + var cookieValue = null; | |
3 | + if (document.cookie && document.cookie !== '') { | |
4 | + var cookies = document.cookie.split(';'); | |
5 | + for (var i = 0; i < cookies.length; i++) { | |
6 | + var cookie = jQuery.trim(cookies[i]); | |
7 | + // Does this cookie string begin with the name we want? | |
8 | + if (cookie.substring(0, name.length + 1) === (name + '=')) { | |
9 | + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); | |
10 | + break; | |
11 | + } | |
12 | + } | |
13 | + } | |
14 | + return cookieValue; | |
15 | +} | |
16 | + | |
17 | + | |
18 | +function createMaterial(url, topic) { | |
19 | + $.ajax({ | |
20 | + url: url, | |
21 | + data: {'topic': topic}, | |
22 | + success: function(data) { | |
23 | + $(".material_form").html(data); | |
24 | + $("#id_topic").val(topic); | |
25 | + | |
26 | + setMaterialCreateFormSubmit(); | |
27 | + } | |
28 | + }); | |
29 | + | |
30 | + $("#editFileModal").modal(); | |
31 | +} | |
32 | + | |
33 | +function setMaterialCreateFormSubmit() { | |
34 | + | |
35 | + var frm = $('#material_create'); | |
36 | + frm.submit(function () { | |
37 | + $.ajax({ | |
38 | + type: frm.attr('method'), | |
39 | + url: frm.attr('action'), | |
40 | + data: frm.serialize(), | |
41 | + success: function (data) { | |
42 | + data = data.split('-'); | |
43 | + | |
44 | + $('.foruns_list').append("<li><i class='fa fa-commenting' aria-hidden='true'></i> <a id='forum_"+data[1]+"' href='"+data[0]+"'> "+data[2]+"</a></li>"); | |
45 | + | |
46 | + $("#createForum").modal('hide'); | |
47 | + | |
48 | + showForum(data[0], data[1]); | |
49 | + }, | |
50 | + error: function(data) { | |
51 | + $(".forum_form").html(data.responseText); | |
52 | + setMaterialCreateFormSubmit(); | |
53 | + } | |
54 | + }); | |
55 | + return false; | |
56 | + }); | |
57 | +} | |
58 | + | |
59 | +function setMaterialUpdateFormSubmit(success_message) { | |
60 | + | |
61 | + var frm = $('#material_create'); | |
62 | + frm.submit(function () { | |
63 | + $.ajax({ | |
64 | + type: frm.attr('method'), | |
65 | + url: frm.attr('action'), | |
66 | + data: frm.serialize(), | |
67 | + success: function (data) { | |
68 | + $('.forum_view').html(data); | |
69 | + | |
70 | + alertify.success(success_message); | |
71 | + | |
72 | + $("#editForum").modal('hide'); | |
73 | + }, | |
74 | + error: function(data) { | |
75 | + $(".forum_form").html(data.responseText); | |
76 | + | |
77 | + setMaterialUpdateFormSubmit(success_message); | |
78 | + } | |
79 | + }); | |
80 | + return false; | |
81 | + }); | |
82 | +} | |
0 | 83 | \ No newline at end of file | ... | ... |
courses/templates/category/create.html
1 | -{% extends 'app/base.html' %} | |
1 | +{% extends 'base.html' %} | |
2 | 2 | |
3 | 3 | {% load static i18n permission_tags %} |
4 | 4 | {% load widget_tweaks %} |
... | ... | @@ -23,7 +23,7 @@ |
23 | 23 | </div> |
24 | 24 | </div> |
25 | 25 | |
26 | -{% if user|has_role:'professor, system_admin' %} | |
26 | +{% if user|has_role:'professor' or user|has_role:'system_admin' %} | |
27 | 27 | |
28 | 28 | <div class="panel panel-primary navigation"> |
29 | 29 | <div class="panel-heading"> | ... | ... |
courses/templates/category/delete.html
1 | -{% extends 'app/base.html' %} | |
1 | +{% extends 'base.html' %} | |
2 | 2 | |
3 | 3 | {% load static i18n %} |
4 | 4 | {% load static i18n permission_tags %} |
... | ... | @@ -23,7 +23,7 @@ |
23 | 23 | </div> |
24 | 24 | </div> |
25 | 25 | |
26 | -{% if user|has_role:'professor, system_admin' %} | |
26 | +{% if user|has_role:'professor' or user|has_role:'system_admin' %} | |
27 | 27 | |
28 | 28 | <div class="panel panel-primary navigation"> |
29 | 29 | <div class="panel-heading"> | ... | ... |
courses/templates/category/index.html
1 | -{% extends 'app/base.html' %} | |
1 | +{% extends 'base.html' %} | |
2 | 2 | |
3 | 3 | {% load static i18n %} |
4 | 4 | {% load static i18n permission_tags %} |
... | ... | @@ -23,8 +23,8 @@ |
23 | 23 | </ul> |
24 | 24 | </div> |
25 | 25 | </div> |
26 | - | |
27 | - {% if user|has_role:'professor, system_admin' %} | |
26 | + | |
27 | + {% if user|has_role:'professor' or user|has_role:'system_admin' %} | |
28 | 28 | |
29 | 29 | <div class="panel panel-primary navigation"> |
30 | 30 | <div class="panel-heading"> | ... | ... |
courses/templates/category/update.html
1 | -{% extends 'app/base.html' %} | |
1 | +{% extends 'base.html' %} | |
2 | 2 | |
3 | 3 | {% load static i18n %} |
4 | 4 | {% load static i18n permission_tags %} |
... | ... | @@ -24,7 +24,7 @@ |
24 | 24 | </div> |
25 | 25 | </div> |
26 | 26 | |
27 | -{% if user|has_role:'professor, system_admin' %} | |
27 | +{% if user|has_role:'professor' or user|has_role:'system_admin' %} | |
28 | 28 | |
29 | 29 | <div class="panel panel-primary navigation"> |
30 | 30 | <div class="panel-heading"> |
... | ... | @@ -87,7 +87,7 @@ |
87 | 87 | {% endif %} |
88 | 88 | {% endfor %} |
89 | 89 | <div class="row text-center"> |
90 | - <input type="submit" value="{% trans 'Save' %}" class="btn btn-sm btn-success" /> | |
90 | + <input type="submit" value="{% trans 'Save' %}" class="btn btn-sm btn-success" /> | |
91 | 91 | </div> |
92 | 92 | </form> |
93 | 93 | </div> | ... | ... |
courses/templates/category/view.html
1 | -{% extends 'app/base.html' %} | |
1 | +{% extends 'base.html' %} | |
2 | 2 | |
3 | 3 | {% load static i18n permission_tags %} |
4 | 4 | {% load widget_tweaks %} |
... | ... | @@ -24,7 +24,7 @@ |
24 | 24 | </ul> |
25 | 25 | </div> |
26 | 26 | </div> |
27 | - {% if user|has_role:'professor, system_admin' %} | |
27 | + {% if user|has_role:'professor' or user|has_role:'system_admin' %} | |
28 | 28 | |
29 | 29 | <div class="panel panel-primary navigation"> |
30 | 30 | <div class="panel-heading"> | ... | ... |
courses/templates/course/index.html
... | ... | @@ -24,7 +24,7 @@ |
24 | 24 | </div> |
25 | 25 | </div> |
26 | 26 | |
27 | -{% if user|has_role:'professor, system_admin' %} | |
27 | +{% if user|has_role:'professor' or user|has_role:'system_admin' %} | |
28 | 28 | |
29 | 29 | <div class="panel panel-primary navigation"> |
30 | 30 | <div class="panel-heading"> |
... | ... | @@ -76,7 +76,7 @@ |
76 | 76 | <i class="material-icons">search</i> |
77 | 77 | </button> |
78 | 78 | </span> |
79 | - </div> | |
79 | + </div> | |
80 | 80 | </form> |
81 | 81 | </div> |
82 | 82 | <div class="col-md-12"> |
... | ... | @@ -103,7 +103,7 @@ |
103 | 103 | <h4 style="color:white">{{course.name}}</h4> |
104 | 104 | </a> |
105 | 105 | </div> |
106 | - {% if user|has_role:'professor, system_admin' %} | |
106 | + {% if user|has_role:'professor' or user|has_role:'system_admin' %} | |
107 | 107 | <div class="col-xs-4 col-md-3" id="divMoreActions"> |
108 | 108 | <div class="btn-group"> |
109 | 109 | <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
... | ... | @@ -150,7 +150,7 @@ |
150 | 150 | <h4 style="color:white">{{course.name}}</h4> |
151 | 151 | </a> |
152 | 152 | </div> |
153 | - {% if user|has_role:'professor, system_admin' %} | |
153 | + {% if user|has_role:'professor' or user|has_role:'system_admin' %} | |
154 | 154 | <div class="col-xs-4 col-md-3" id="divMoreActions"> |
155 | 155 | <div class="btn-group"> |
156 | 156 | <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | ... | ... |
courses/templates/course/view.html
... | ... | @@ -28,7 +28,7 @@ |
28 | 28 | </div> |
29 | 29 | </div> |
30 | 30 | |
31 | -{% if user|has_role:'professor, system_admin' %} | |
31 | +{% if user|has_role:'professor' or user|has_role:'system_admin' %} | |
32 | 32 | |
33 | 33 | <div class="panel panel-primary navigation"> |
34 | 34 | <div class="panel-heading"> |
... | ... | @@ -48,7 +48,14 @@ |
48 | 48 | {% endblock %} |
49 | 49 | |
50 | 50 | {% block content %} |
51 | - | |
51 | +<div class="col-md-12"> | |
52 | + <div class="btn-group btn-group-justified btn-group-raised"> | |
53 | + <a href="?category=all" class="btn btn-raised btn-info">Todos</a> | |
54 | + {% for category_subject in categorys_subjects %} | |
55 | + <a href="?category={{category_subject.name}}" class="btn btn-raised btn-primary">{{category_subject.name}}</a> | |
56 | + {% endfor %} | |
57 | + </div> | |
58 | +</div> | |
52 | 59 | <div class="col-md-12"> |
53 | 60 | <div class="panel panel-info"> |
54 | 61 | <div class="panel-heading headingOne"> |
... | ... | @@ -157,7 +164,9 @@ |
157 | 164 | </div> |
158 | 165 | |
159 | 166 | <div class="panel-group ui-accordion ui-widget ui-helper-reset ui-sortable" id="accordion" role="tablist" aria-multiselectable="false"> |
160 | - <div><div class="panel panel-info"> | |
167 | + <div> | |
168 | + | |
169 | + <div class="panel panel-info"> | |
161 | 170 | </div> |
162 | 171 | |
163 | 172 | |
... | ... | @@ -182,60 +191,105 @@ |
182 | 191 | </div> |
183 | 192 | </div> |
184 | 193 | <div> |
185 | - | |
186 | -{% for subject in subjects %} | |
187 | -<div class="panel panel-info"> | |
188 | - <div class="panel-heading headingTwo ui-sortable-handle" role="tab"> | |
189 | - <div class="row"> | |
190 | - <div class="col-xs-9 col-md-10 titleTopic"> | |
191 | - <a role="button" data-toggle="collapse" data-parent="#accordion" href=".collapseTwo" aria-expanded="true" aria-controls="collapseTwo"> | |
192 | - <h4 style="color:white">{{subject.name}}</h4> | |
193 | - </a> | |
194 | - </div> | |
195 | - <div class="col-xs-3 col-md-2" id="divMoreActions"> | |
196 | - <div class="btn-group"> | |
197 | - <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | |
198 | - <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> | |
199 | - </button> | |
200 | - <ul class="dropdown-menu" aria-labelledby="moreActions"> | |
201 | - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal3"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i> Replicate</a></li> | |
202 | - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeSubject2"><i class="fa fa-trash fa-fw" aria-hidden="true"></i> Remove</a></li> | |
203 | - </ul> | |
194 | + {% if request.GET.category == 'all' or none or request.GET.category == '' %} | |
195 | + {% for subject in subjects %} | |
196 | + <div class="panel panel-info"> | |
197 | + <div class="panel-heading headingTwo ui-sortable-handle" role="tab"> | |
198 | + <div class="row"> | |
199 | + <div class="col-xs-9 col-md-10 titleTopic"> | |
200 | + <a role="button" data-toggle="collapse" data-parent="#accordion" href=".collapseTwo" aria-expanded="true" aria-controls="collapseTwo"> | |
201 | + <h4 style="color:white">{{subject.name}}</h4> | |
202 | + </a> | |
203 | + </div> | |
204 | + <div class="col-xs-3 col-md-2" id="divMoreActions"> | |
205 | + <div class="btn-group"> | |
206 | + <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | |
207 | + <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> | |
208 | + </button> | |
209 | + <ul class="dropdown-menu" aria-labelledby="moreActions"> | |
210 | + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal3"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i> Replicate</a></li> | |
211 | + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeSubject2"><i class="fa fa-trash fa-fw" aria-hidden="true"></i> Remove</a></li> | |
212 | + </ul> | |
213 | + </div> | |
214 | + </div> | |
215 | + </div> | |
204 | 216 | </div> |
217 | + <div class="panel-body"> | |
218 | + <p><b>{% trans "Professor" %}: </b>{% for professor in subject.professors.all %}{% if not forloop.first %},{% endif %} | |
219 | + {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}</p> | |
220 | + <p> | |
221 | + <b>{% trans "Description" %}: </b> | |
222 | + <i> | |
223 | + {{subject.description}} | |
224 | + </i> | |
225 | + </p> | |
226 | + <div class="row"> | |
227 | + <div class="col-xs-6 col-md-6"> | |
228 | + <p><b>{% trans "Begining" %}: </b>{{subject.init_date}}</p> | |
229 | + </div> | |
230 | + <div class="col-xs-6 col-md-6"> | |
231 | + <p><b>{% trans "End" %}: </b>{{subject.end_date}}</p> | |
232 | + </div> | |
233 | + </div> | |
234 | + <a href="{% url 'course:view_subject' subject.slug %}" class="btn btn-raised btn-default center-block">{% trans 'View Subject' %}<div class="ripple-container"></div></a> | |
235 | + </div> | |
205 | 236 | </div> |
206 | - </div> | |
207 | - </div> | |
208 | - <div class="panel-body"> | |
209 | - <p><b>{% trans "Professor" %}: </b>{% for professor in subject.professors.all %}{% if not forloop.first %},{% endif %} | |
210 | - {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}</p> | |
211 | - <p> | |
212 | - <b>{% trans "Description" %}: </b> | |
213 | - <i> | |
214 | - {{subject.description}} | |
215 | - </i> | |
216 | - </p> | |
217 | - <div class="row"> | |
218 | - <div class="col-xs-6 col-md-6"> | |
219 | - <p><b>{% trans "Begining" %}: </b>{{subject.init_date}}</p> | |
220 | - </div> | |
221 | - <div class="col-xs-6 col-md-6"> | |
222 | - <p><b>{% trans "End" %}: </b>{{subject.end_date}}</p> | |
237 | + {% endfor %} | |
238 | + {% else %} | |
239 | + {% for subject in subjects_category %} | |
240 | + {% if subject.category.name == request.GET.category %} | |
241 | + <div class="panel panel-info"> | |
242 | + <div class="panel-heading headingTwo ui-sortable-handle" role="tab"> | |
243 | + <div class="row"> | |
244 | + <div class="col-xs-9 col-md-10 titleTopic"> | |
245 | + <a role="button" data-toggle="collapse" data-parent="#accordion" href=".collapseTwo" aria-expanded="true" aria-controls="collapseTwo"> | |
246 | + <h4 style="color:white">{{subject.name}}</h4> | |
247 | + </a> | |
248 | + </div> | |
249 | + <div class="col-xs-3 col-md-2" id="divMoreActions"> | |
250 | + <div class="btn-group"> | |
251 | + <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | |
252 | + <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> | |
253 | + </button> | |
254 | + <ul class="dropdown-menu" aria-labelledby="moreActions"> | |
255 | + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal3"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i> Replicate</a></li> | |
256 | + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeSubject2"><i class="fa fa-trash fa-fw" aria-hidden="true"></i> Remove</a></li> | |
257 | + </ul> | |
258 | + </div> | |
259 | + </div> | |
260 | + </div> | |
223 | 261 | </div> |
262 | + <div class="panel-body"> | |
263 | + <p><b>{% trans "Professor" %}: </b>{% for professor in subject.professors.all %}{% if not forloop.first %},{% endif %} | |
264 | + {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}</p> | |
265 | + <p> | |
266 | + <b>{% trans "Description" %}: </b> | |
267 | + <i> | |
268 | + {{subject.description}} | |
269 | + </i> | |
270 | + </p> | |
271 | + <div class="row"> | |
272 | + <div class="col-xs-6 col-md-6"> | |
273 | + <p><b>{% trans "Begining" %}: </b>{{subject.init_date}}</p> | |
274 | + </div> | |
275 | + <div class="col-xs-6 col-md-6"> | |
276 | + <p><b>{% trans "End" %}: </b>{{subject.end_date}}</p> | |
277 | + </div> | |
278 | + </div> | |
279 | + <a href="{% url 'course:view_subject' subject.slug %}" class="btn btn-raised btn-default center-block">{% trans 'View Subject' %}<div class="ripple-container"></div></a> | |
280 | + </div> | |
224 | 281 | </div> |
225 | - <a href="{% url 'course:view_subject' subject.slug %}" class="btn btn-raised btn-default center-block">{% trans 'View Subject' %}<div class="ripple-container"></div></a> | |
226 | - </div> | |
227 | -</div> | |
282 | + {% endif %} | |
283 | + {% endfor %} | |
284 | + {% endif %} | |
285 | + | |
228 | 286 | {% if user|has_role:'professor' or user|has_role:'system_admin' %} |
229 | - | |
287 | + | |
230 | 288 | <div class="form-group"> |
231 | - <a href="{% url 'course:create_subject' subject.slug %}" data-toggle="modal" data-target="" class="btn btn-primary btn-lg btn-block btn-raised">{% trans 'Create Subject' %}<div class="ripple-container"></div></a> | |
289 | + <a href="#" data-toggle="modal" data-target="" class="btn btn-primary btn-lg btn-block btn-raised">{% trans 'Create Subject' %}<div class="ripple-container"></div></a> | |
232 | 290 | </div> |
233 | 291 | {% endif %} |
234 | 292 | |
235 | - | |
236 | -{% endfor %} | |
237 | - | |
238 | - | |
239 | 293 | <!-- MODAL REMOVE --> |
240 | 294 | <div class="modal" id="removeSubject2"> |
241 | 295 | <div class="modal-dialog"> |
... | ... | @@ -262,4 +316,3 @@ |
262 | 316 | </div> |
263 | 317 | |
264 | 318 | {% endblock %} |
265 | - | ... | ... |
courses/templates/subject/form_view_teacher.html
1 | - {% load static i18n list_topic_foruns permission_tags %} | |
1 | + {% load static i18n list_topic_foruns permission_tags widget_tweaks professor_access%} | |
2 | 2 | |
3 | 3 | {% block javascript %} |
4 | 4 | <script type="text/javascript" src="{% static 'js/forum.js' %}"></script> |
5 | + <script src="{% static 'js/file.js' %}"></script> | |
6 | + <script type="text/javascript" src="{% static 'js/material.js' %}"></script> | |
7 | + <script type = "text/javascript" src="{% static 'link.js' %}"></script> | |
5 | 8 | {% endblock %} |
6 | 9 | |
7 | 10 | <div class="panel-group accordion ui-accordion ui-widget ui-helper-reset ui-sortable" role="tablist" aria-multiselectable="false"> |
... | ... | @@ -23,7 +26,8 @@ |
23 | 26 | <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
24 | 27 | <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> |
25 | 28 | </button> |
26 | - {% if user|has_role:'system_admin' or topic.owner == user %} | |
29 | + {% professor_subject topic.subject user as dropdown_topic %} | |
30 | + {% if dropdown_topic %} | |
27 | 31 | <ul class="dropdown-menu pull-right" aria-labelledby="moreActions"> |
28 | 32 | <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal4"><i class="fa fa-files-o fa-fw" aria-hidden="true"></i> {% trans "Replicate" %}</a></li> |
29 | 33 | <li><a href="javascript:void(0)" class="edit_card"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i> {% trans "Edit" %}</a></li> |
... | ... | @@ -51,14 +55,22 @@ |
51 | 55 | <div class="dropdown"> |
52 | 56 | <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> |
53 | 57 | <ul class="dropdown-menu" aria-labelledby="dLabel"> |
54 | - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#createLinksModal">Create a Link<div class="ripple-container"><div class="ripple ripple-on ripple-out" style="left: 54.5312px; top: 22px; background-color: rgb(0, 150, 136); transform: scale(20);"></div></div></a></li> | |
55 | - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#createFileModal">Create a file<div class="ripple-container"><div class="ripple ripple-on ripple-out" style="left: 33.5312px; top: 11px; background-color: rgb(0, 150, 136); transform: scale(20);"></div></div></a></li> | |
58 | + <li><a href=" javascript:get_modal_link('{% url 'course:links:create_link' %}', '#createLinksModal','#divModalLink') ">Create a Link<div class="ripple-container"><div class="ripple ripple-on ripple-out" style="left: 54.5312px; top: 22px; background-color: rgb(0, 150, 136); transform: scale(20);"></div></div></a></li> | |
59 | + <li> | |
60 | + <a href="javascript:get_modal_file('{% url 'course:file:create_file' topic.slug %}', '#fileModal', '#divModalFile')"> | |
61 | + {% trans "Create a file" %} | |
62 | + <div class="ripple-container"> | |
63 | + <div class="ripple ripple-on ripple-out" style="left: 33.5312px; top: 11px; background-color: rgb(0, 150, 136); transform: scale(20);"> | |
64 | + </div> | |
65 | + </div> | |
66 | + </a> | |
67 | + </li> | |
56 | 68 | </ul> |
57 | 69 | </div> |
58 | 70 | </div> |
59 | 71 | <ul> |
60 | - <li><i class="fa fa-book" aria-hidden="true"></i> <a href="#">Book 1</a></li> | |
61 | - <li><i class="fa fa-link" aria-hidden="true"></i> <a href="#" data-toggle="modal" data-target="#linksModal">Link 1</a></li> | |
72 | + {% list_topic_file request topic %} | |
73 | + {% list_topic_link request topic%} | |
62 | 74 | <li><i class="fa fa-file-code-o" aria-hidden="true"></i> <a href="#" data-toggle="modal" data-target="#embedModal">EMBED Material</a></li> |
63 | 75 | </ul> |
64 | 76 | </div> |
... | ... | @@ -71,6 +83,8 @@ |
71 | 83 | <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> |
72 | 84 | <ul class="dropdown-menu" aria-labelledby="dLabel"> |
73 | 85 | <li><a href="javascript:createForum('{% url 'course:forum:create' %}', '{{ topic.id }}')">{% trans 'Create Forum' %}<div class="ripple-container"><div class="ripple ripple-on ripple-out" style="left: 33.5312px; top: 11px; background-color: rgb(0, 150, 136); transform: scale(20);"></div></div></a></li> |
86 | + <li><a href="javascript:modal.get('{% url 'course:poll:create_poll' topic.slug%}','#poll','#modal_poll');">{% trans 'Create Poll' %}</a></li> | |
87 | + | |
74 | 88 | </ul> |
75 | 89 | </div> |
76 | 90 | </div> |
... | ... | @@ -102,18 +116,14 @@ |
102 | 116 | <div class="dropdown"> |
103 | 117 | <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> |
104 | 118 | <ul class="dropdown-menu" aria-labelledby="dLabel"> |
105 | - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#createLinksModal">Create a Link</a></li> | |
106 | - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#createFileModal">Create a file</a></li> | |
119 | + <li><a href=" javascript:get_modal_link('{% url 'course:links:create_link' %}', '#createLinksModal','#divModalLink') ">Create a Link</a></li> | |
120 | + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#fileModal">Create a file</a></li> | |
107 | 121 | </ul> |
108 | 122 | </div> |
109 | 123 | </div> |
110 | 124 | <ul> |
111 | - <li class="icon_edit_remove"> <a href="#" data-toggle="modal" data-target="#editFileModal"><i class="fa fa-pencil fa-lg" aria-hidden="true"></i></a> <a href="#" data-toggle="modal" data-target="#removeFileModal"><i class="fa fa-trash fa-lg" aria-hidden="true"></i></a></li> | |
112 | - <li><a href="#">Book 1</a> </li> | |
113 | - <li class="icon_edit_remove"> <a href="#" data-toggle="modal" data-target="#linksModalEdit"><i class="fa fa-pencil fa-lg" aria-hidden="true"></i></a> <a href="#" data-toggle="modal" data-target="#removeLink"><i class="fa fa-trash fa-lg" aria-hidden="true"></i></a></li> | |
114 | - <li><a href="#" data-toggle="modal" data-target="#linksModal">Link 1</a></li> | |
115 | - <li class="icon_edit_remove"><i class="fa fa-pencil fa-lg" aria-hidden="true"></i> <i class="fa fa-trash fa-lg" aria-hidden="true"></i></li> | |
116 | - <li><a href="#" data-toggle="modal" data-target="#embedModal">EMBED Material</a></li> | |
125 | + {% list_topic_link_edit request topic%} | |
126 | + {% list_topic_file_edit request topic %} | |
117 | 127 | </ul> |
118 | 128 | </div> |
119 | 129 | <div class="col-xs-4 col-md-offset-1 col-md-4"> |
... | ... | @@ -167,116 +177,9 @@ |
167 | 177 | </div> |
168 | 178 | </div> |
169 | 179 | <!-- END --> |
170 | - | |
171 | - <!-- MODAL EDIT FILE --> | |
172 | - <div class="modal fade" id="editFileModal" tabindex="-1" role="dialog" aria-labelledby="editFileLabel"> | |
173 | - <div class="modal-dialog" role="document"> | |
174 | - <div class="modal-content"> | |
175 | - <div class="modal-header"> | |
176 | - <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
177 | - <h4 class="modal-title" id="editFileLabel">Add File</h4> | |
178 | - </div> | |
179 | - <div class="modal-body"> | |
180 | - <!-- Card --> | |
181 | - | |
182 | - <form class="form-horizontal"> | |
183 | - <fieldset> | |
184 | - | |
185 | - <div class="form-group"> | |
186 | - <label for="inputName" class="col-md-2 control-label">Name</label> | |
187 | - | |
188 | - <div class="col-md-10"> | |
189 | - <input type="text" class="form-control" id="inputText" placeholder="Name" value="Book 1"> | |
190 | - </div> | |
191 | - </div> | |
192 | - | |
193 | - <div class="form-group is-empty is-fileinput"> | |
194 | - <label for="inputFile" class="col-md-2 control-label">File</label> | |
195 | - | |
196 | - <div class="col-md-10"> | |
197 | - <input type="text" readonly="" class="form-control" placeholder="Browse..."> | |
198 | - <input type="file" id="inputFile" multiple=""> | |
199 | - </div> | |
200 | - </div> | |
201 | - | |
202 | - | |
203 | - <div class="form-group"> | |
204 | - <div class="col-md-12 text-center"> | |
205 | - <p><b>The file size shouldn't exceed 10MB</b></p> | |
206 | - </div> | |
207 | - </div> | |
208 | - | |
209 | - <div class="form-group"> | |
210 | - <div class="col-md-12"> | |
211 | - <a href="javascript:void(0)" class="btn btn-raised btn-default">Cancel</a> | |
212 | - <a href="javascript:void(0)" class="btn btn-raised btn-primary">Submit</a> | |
213 | - </div> | |
214 | - </div> | |
215 | - </fieldset> | |
216 | - </form> | |
217 | - | |
218 | - | |
219 | - <!-- .end Card --> | |
220 | - </div> | |
221 | - </div> | |
222 | - </div> | |
223 | - </div> | |
224 | - | |
225 | -{% if user|has_role:'system_admin' or topic.owner == user%} | |
226 | - {% include "files/create_file.html" %} | |
227 | -{% endif %} | |
228 | - <!-- MODAL REMOVE FILE --> | |
229 | - <div class="modal" id="removeFileModal"> | |
230 | - <div class="modal-dialog"> | |
231 | - <div class="modal-content"> | |
232 | - <div class="modal-header"> | |
233 | - <button type="button" class="close" data-dismiss="modal" aria-hidden="true">X</button> | |
234 | - <h4 class="modal-title"></h4> | |
235 | - </div> | |
236 | - <div class="modal-body"> | |
237 | - <p>Do you really want to delete this file?</p> | |
238 | - </div> | |
239 | - <div class="modal-footer"> | |
240 | - | |
241 | - <a href="#" target="_self"><button type="button" class="btn btn-primary" data-dismiss="modal" aria-hidden="true">Confirm</button></a> | |
242 | - | |
243 | - </div> | |
244 | - </div> | |
245 | - </div> | |
246 | - </div> | |
247 | - <!-- END --> | |
248 | - | |
249 | - <!--MODAL VIEW LINK--> | |
250 | - <div class="modal fade" id="linksModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> | |
251 | - <div class="modal-dialog" role="document"> | |
252 | - <div class="modal-content"> | |
253 | - <div class="modal-header"> | |
254 | - <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
255 | - <h4 class="modal-title" id="myModalLabel">Links</h4> | |
256 | - </div> | |
257 | - <div class="modal-body"> | |
258 | - <!-- Card --> | |
259 | - <article class="card animated fadeInLeft"> | |
260 | - <img class="card-img-top img-responsive" src="https://www.python.org/static/opengraph-icon-200x200.png" align="left"> | |
261 | - <div class="card-block"> | |
262 | - <b class="card-title">Python</b><p></p> | |
263 | - <b class="text-muted">Guido van Rossum</b> | |
264 | - <p class="card-text"> </p><p>Python is a widely used high-level, general-purpose, interpreted, dynamic programming language. Its design philosophy emphasizes code readability, and its syntax allows programmers to express concepts in fewer lines of code than possible in languages such as C++ or Java.</p> | |
265 | - <a href="https://www.python.org/" class="btn btn-primary">Read more</a> | |
266 | - </div> | |
267 | - </article> | |
268 | - <!-- .end Card --> | |
269 | - </div> | |
270 | - </div> | |
271 | - </div> | |
272 | - </div> | |
273 | - <!-- EndModal --> | |
274 | - | |
275 | - {% if user|has_role:'system_admin' or topic.owner == user%} | |
180 | + {% professor_subject topic.subject user as professor_links %} | |
181 | + {% if professor_links%} | |
276 | 182 | {% include "links/create_link.html" %} |
277 | - {% endif %} | |
278 | - | |
279 | - {% if user|has_role:'system_admin' or topic.owner == user%} | |
280 | 183 | {% include "links/delete_link.html" %} |
281 | 184 | {% endif %} |
282 | 185 | |
... | ... | @@ -332,7 +235,7 @@ |
332 | 235 | <!-- EndModal --> |
333 | 236 | |
334 | 237 | <!-- MODAL ACTIVITIES--> |
335 | - <div class="modal fade" id="ActivityModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> | |
238 | + <div class="modal fade" id="ActivityModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> | |
336 | 239 | <div class="modal-dialog" role="document"> |
337 | 240 | <div class="modal-content"> |
338 | 241 | <div class="modal-header"> |
... | ... | @@ -393,139 +296,11 @@ |
393 | 296 | </div> |
394 | 297 | <!--EndModal--> |
395 | 298 | |
396 | - <!-- MODAL FORUM --> | |
397 | - <div class="modal fade" id="forumModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> | |
398 | - <div class="modal-dialog" role="document"> | |
399 | - <div class="modal-content"> | |
400 | - <div class="modal-header"> | |
401 | - <h4 class="modal-title" id="myModalLabel">Forum</h4> | |
402 | - </div> | |
403 | - <div class="modal-body"> | |
404 | - <!--Forum--> | |
405 | - <!--Main wrapper--> | |
406 | - <div class="comments-list"> | |
407 | - <div class="section-heading"> | |
408 | - <h1>Python</h1> | |
409 | - <h4><b>Description:</b>High-level Language</h4> | |
410 | - <h4><b>Opened in:</b> September 1st</h4> | |
411 | - </div> | |
412 | - <!--First row--> | |
413 | - <div class="row"> | |
414 | - | |
415 | - <!--Content column--> | |
416 | - <div class="col-sm-10 col-xs-12"> | |
417 | - <h3 class="user-name">Gerson Jefferson</h3> | |
418 | - | |
419 | - <div class="card-data"> | |
420 | - <p class="comment-date"><i class="fa fa-clock-o"></i> 05/10/2015</p> | |
421 | - </div> | |
422 | 299 | |
423 | - <p class="comment-text">Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat | |
424 | - cupidatat non proident.</p> | |
425 | - </div> | |
426 | - <!--/.Content column--> | |
427 | - </div> | |
428 | - <a class="btn btn-sm" style="float: right;" data-toggle="collapse" href="#collapse1" aria-expanded="false" aria-controls="collapseExample">Reply</a> | |
429 | - <div class="collapse" id="collapse1"> | |
430 | - <div class="md-form"> | |
431 | - <div class="form-group is-empty"><input type="text" id="form1" class="form-control" placeholder="comment on the cometary"></div><span class="input-group-btn"> | |
432 | - <button type="button" class="btn btn-sm"> | |
433 | - <i class="fa fa-paper-plane"> Send</i> | |
434 | - </button> | |
435 | - </span> | |
436 | - </div> | |
437 | - </div> | |
438 | - </div> | |
439 | - | |
440 | - <!--/.First row--> | |
441 | - | |
442 | - <!--Second row--> | |
443 | - <div class="row"> | |
444 | - | |
445 | - <!--Content column--> | |
446 | - <div class="col-sm-10 col-xs-12"> | |
447 | - <h3 class="user-name">Cherielly</h3> | |
448 | - | |
449 | - <div class="card-data"> | |
450 | - <p class="comment-date"><i class="fa fa-clock-o"></i> 08/10/2015</p> | |
451 | - </div> | |
452 | - | |
453 | - <p class="comment-text">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam | |
454 | - voluptatem quia voluptas sit aspernatur.</p> | |
455 | - </div> | |
456 | - <!--/.Content column--> | |
457 | - </div> | |
458 | - <a class="btn btn-sm" style="float: right;" data-toggle="collapse" href="#collapse2" aria-expanded="false" aria-controls="collapseExample">Reply</a> | |
459 | - <div class="collapse" id="collapse2"> | |
460 | - <div class="md-form"> | |
461 | - <div class="form-group is-empty"><input type="text" id="form1" class="form-control" placeholder="comment on the cometary"></div><span class="input-group-btn"> | |
462 | - <button type="button" class="btn btn-sm"> | |
463 | - <i class="fa fa-paper-plane"> Send</i> | |
464 | - </button> | |
465 | - </span> | |
466 | - </div> | |
467 | - </div> | |
468 | - | |
469 | - | |
470 | - <!--/.Second row--> | |
471 | - | |
472 | - <!--Third row--> | |
473 | - <div class="row"> | |
474 | - | |
475 | - | |
476 | - <!--Content column--> | |
477 | - <div class="col-sm-10 col-xs-12"> | |
478 | - <h3 class="user-name">Gemozecleia</h3> | |
479 | - | |
480 | - <div class="card-data"> | |
481 | - <p class="comment-date"><i class="fa fa-clock-o"></i> 17/10/2015 | |
482 | - </p></div> | |
483 | - | |
484 | - <p class="comment-text">At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa | |
485 | - qui officia. | |
486 | - </p> | |
487 | - </div> | |
488 | - <!--/.Content column--> | |
489 | - | |
490 | - </div> | |
491 | - <a class="btn btn-sm" style="float: right;" data-toggle="collapse" href="#collapse3" aria-expanded="false" aria-controls="collapseExample">Reply</a> | |
492 | - <div class="collapse" id="collapse3"> | |
493 | - <div class="md-form"> | |
494 | - <div class="form-group is-empty"><input type="text" id="form1" class="form-control" placeholder="comment on the cometary"></div><span class="input-group-btn"> | |
495 | - <button type="button" class="btn btn-sm"> | |
496 | - <i class="fa fa-paper-plane"> Send</i> | |
497 | - </button> | |
498 | - </span> | |
499 | - </div> | |
500 | - </div> | |
501 | - | |
502 | - <!--/.Third row--> | |
503 | - <div class="row"> | |
504 | - <div class="form-group is-empty"> | |
505 | - <div class="col-sm-10 col-xs-12"> | |
506 | - <input type="text" id="addon3a" class="form-control" placeholder="Add Comment"> | |
507 | - | |
508 | - <span class="input-group-btn"> | |
509 | - <button type="button" class="btn btn-fab btn-fab-mini"> | |
510 | - <i class="material-icons">send</i> | |
511 | - </button> | |
512 | - </span> | |
513 | - </div> | |
514 | - </div> | |
515 | - </div> | |
516 | - | |
517 | - </div> | |
518 | - <div class="modal-footer"> | |
519 | - <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> | |
520 | - <button type="button" class="btn btn-primary">Save changes</button> | |
521 | - </div> | |
522 | - </div> | |
523 | - </div> | |
524 | - </div> | |
525 | - <!--EndForumModal--> | |
526 | 300 | |
527 | 301 | <!-- MODAL LINK EDIT--> |
528 | - {% if user|has_role:'system_admin' or topic.owner == user%} | |
302 | + {% professor_subject topic.subject user as links_update %} | |
303 | + {% if links_update%} | |
529 | 304 | {% include "links/update_link.html" %} |
530 | 305 | {% endif %} |
531 | 306 | ... | ... |
courses/templates/subject/index.html
1 | 1 | {% extends 'base.html' %} |
2 | 2 | |
3 | -{% load static i18n permission_tags %} | |
3 | +{% load static i18n permission_tags professor_access%} | |
4 | 4 | |
5 | 5 | {% block breadcrumbs %} |
6 | 6 | |
... | ... | @@ -12,7 +12,7 @@ |
12 | 12 | {% else %} |
13 | 13 | <li class="active">{{ subject.name }}</li> |
14 | 14 | {% endif %} |
15 | - | |
15 | + | |
16 | 16 | </ol> |
17 | 17 | {% endblock %} |
18 | 18 | |
... | ... | @@ -28,7 +28,7 @@ |
28 | 28 | </ul> |
29 | 29 | </div> |
30 | 30 | </div> |
31 | - | |
31 | + | |
32 | 32 | |
33 | 33 | {% endblock %} |
34 | 34 | |
... | ... | @@ -39,7 +39,8 @@ |
39 | 39 | <div class="col-md-9 col-sm-9"> |
40 | 40 | <h3>{{subject}}</h3> |
41 | 41 | </div> |
42 | - {% if user|has_role:'system_admin' or user in subject.professors %} | |
42 | + {% professor_subject subject user as subject_professor%} | |
43 | + {% if subject_professor %} | |
43 | 44 | <div class="col-xs-4 col-md-3 divMoreActions"> |
44 | 45 | <div class="btn-group"> |
45 | 46 | <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
... | ... | @@ -71,19 +72,20 @@ |
71 | 72 | </div> |
72 | 73 | </div> |
73 | 74 | </div> |
74 | - | |
75 | + | |
75 | 76 | {% for topic in topics %} |
76 | - {% if user|has_role:'system_admin' or topic.owner == user%} | |
77 | + {% professor_subject topic.subject user as topic_professor%} | |
78 | + {% if topic_professor %} | |
77 | 79 | {% include "subject/form_view_teacher.html" %} |
78 | 80 | {% else %} |
79 | 81 | {% include "subject/form_view_student.html" %} |
80 | 82 | {% endif %} |
81 | 83 | {% endfor %} |
82 | - | |
83 | - {% if user|has_role:'system_admin' or topic.owner == user%} | |
84 | + {% professor_subject subject user as professor_sub %} | |
85 | + {% if professor_sub %} | |
84 | 86 | <div class="form-group"> |
85 | 87 | <a href="{% url 'course:create_topic' subject.slug %}" data-toggle="modal" data-target="" class="btn btn-primary btn-lg btn-block btn-raised" name="create_topic">{% trans "Create Topic" %}<div class="ripple-container"></div></a> |
86 | 88 | </div> |
87 | - {% endif %} | |
89 | + {% endif %} | |
88 | 90 | |
89 | 91 | {% endblock %} | ... | ... |
courses/templates/subject/poll_item_actions.html
1 | -{% load static i18n permission_tags%} | |
1 | +{% load static i18n permission_tags professor_access %} | |
2 | 2 | |
3 | 3 | <script src="{% static 'js/modals_requisitions.js'%}"></script> |
4 | 4 | <script src="{% static 'js/modal_poll.js'%}"></script> |
5 | 5 | |
6 | -{% if request.user|has_role:'professor, system_admin'%} | |
7 | 6 | {% for poll in polls %} |
8 | - <li id="poll_{{poll.slug}}"><i class="material-icons">poll</i> <a href="javascript:get('{% url 'course:poll:update_poll' poll.slug %}','#poll','#modal_poll');">{{ poll.name }}</a><a href="javascript:get('{% url 'course:poll:delete_poll' poll.slug %}','#poll','#modal_poll');"><span class="glyphicon glyphicon-remove"></span></a></li> | |
9 | -{% endfor %} | |
10 | -<button class="btn btn-primary btn-raised" onclick="javascript:get('{% url 'course:poll:create_poll' topic.slug%}','#poll','#modal_poll');">{% trans '+ Create Poll' %}</button> | |
11 | -{% else %} | |
12 | -{% for poll in polls %} | |
13 | - <li id="poll_{{poll.slug}}"><i class="material-icons">poll</i> <a href="javascript:get('{% url 'course:poll:view_poll' poll.slug %}','#poll','#modal_poll');">{{ poll.name }}</a></li> | |
14 | -{% endfor %} | |
15 | -{% endif %} | |
7 | + {% professor_subject poll.topic.subject request.user as permission%} | |
8 | + {% if permission %} | |
9 | + <li id="poll_{{poll.slug}}"><i class="material-icons">poll</i> <a href="javascript:modal.get('{% url 'course:poll:update_poll' poll.slug %}','#poll','#modal_poll');">{{ poll.name }}</a><a href="javascript:modal.get('{% url 'course:poll:delete_poll' poll.slug %}','#poll','#modal_poll');"><span class="glyphicon glyphicon-remove"></span></a></li> | |
10 | + {% else %} | |
11 | + <li id="poll_{{poll.slug}}"><i class="material-icons">poll</i> <a href="javascript:modal.get('{% url 'course:poll:view_poll' poll.slug %}','#poll','#modal_poll');">{{ poll.name }}</a></li> | |
12 | + {% endif %} | |
13 | + {% endfor %} | |
14 | +{# <button class="btn btn-primary btn-raised" onclick="javascript:modal.get('{% url 'course:poll:create_poll' topic.slug%}','#poll','#modal_poll');">{% trans '+ Create Poll' %}</button> #} | |
16 | 15 | <div class="row" id="modal_poll"> |
17 | 16 | |
18 | 17 | </div> | ... | ... |
courses/templates/subject_category/index.html
1 | 1 | {% extends 'base.html' %} |
2 | 2 | |
3 | -{% load static i18n permission_tags %} | |
3 | +{% load static i18n permission_tags professor_access%} | |
4 | 4 | |
5 | 5 | {% block breadcrumbs %} |
6 | 6 | |
7 | 7 | <ol class="breadcrumb"> |
8 | 8 | <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> |
9 | - | |
10 | - | |
9 | + | |
10 | + | |
11 | 11 | </ol> |
12 | 12 | {% endblock %} |
13 | 13 | |
... | ... | @@ -43,12 +43,14 @@ |
43 | 43 | <h3>{{subject}}</h3> |
44 | 44 | </div> |
45 | 45 | <div class="col-md-2 col-sm-2"> |
46 | - {% if user|has_role:'system_admin' or user in subject.professors %} | |
46 | + {% professor_subject subject user as professor_sub%} | |
47 | + {% if professor_sub %} | |
47 | 48 | <a href="" class="btn">{% trans "edit" %}</a> |
48 | 49 | {% endif %} |
49 | 50 | </div> |
50 | 51 | <div class="col-md-3 col-sm-3"> |
51 | - {% if user|has_role:'system_admin' or user in subject.professors %} | |
52 | + {% professor_subject subject user as delete_sub%} | |
53 | + {% if delete_sub %} | |
52 | 54 | <a href="" class="btn">{% trans "delete" %}</a> |
53 | 55 | {% endif %} |
54 | 56 | </div> |
... | ... | @@ -60,6 +62,6 @@ |
60 | 62 | </p> |
61 | 63 | </div> |
62 | 64 | </div> |
63 | - | |
65 | + | |
64 | 66 | |
65 | 67 | {% endblock %} | ... | ... |
courses/templates/topic/index.html
1 | 1 | {% extends 'base.html' %} |
2 | 2 | |
3 | -{% load static i18n permission_tags %} | |
3 | +{% load static i18n permission_tags professor_access %} | |
4 | 4 | |
5 | 5 | {% block breadcrumbs %} |
6 | 6 | |
7 | 7 | <ol class="breadcrumb"> |
8 | 8 | <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> |
9 | 9 | <li><a href="{% url 'course:view_subject' subject.slug %}">{{ subject }}</a></li> |
10 | - {% if user|has_role:'professor' or user|has_role:'system_admin' %} | |
10 | + {% professor_subject subject user as maneger_topic%} | |
11 | + {% if maneger_topic %} | |
11 | 12 | <li class="active">{% trans 'Manage Topic' %}</li> |
12 | 13 | {% else %} |
13 | 14 | <li class="active">{{ topic.name }}</li> |
... | ... | @@ -54,7 +55,8 @@ |
54 | 55 | <h3>{{subject}}</h3> |
55 | 56 | </div> |
56 | 57 | <div class="col-xs-4 col-md-2 divMoreActions"> |
57 | - {% if user|has_role:'system_admin' or user in subject.professors %} | |
58 | + {% professor_subject subject user as permissions%} | |
59 | + {% if permissions %} | |
58 | 60 | <div class="btn-group"> |
59 | 61 | <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
60 | 62 | <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> |
... | ... | @@ -105,7 +107,8 @@ |
105 | 107 | <div class="col-md-4"> |
106 | 108 | <i class="fa fa-file-archive-o fa-lg" aria-hidden="true">Atividade.doc</i> |
107 | 109 | </div> |
108 | - {% if user|has_role:'professor, system_admin' %} | |
110 | + {% professor_subject subject user as permi_test%} | |
111 | + {% if permi_test %} | |
109 | 112 | <div class="col-md-4"> |
110 | 113 | <label> Nota:</label> |
111 | 114 | <input type="number" step="0.01"> | ... | ... |
... | ... | @@ -0,0 +1,27 @@ |
1 | +{% load static i18n list_topic_foruns permission_tags %} | |
2 | +{% for link in links%} | |
3 | + <li><i class="fa fa-link" aria-hidden="true"></i> <a href="#" data-toggle="modal" data-target="#linksModal{{slug}}{{ forloop.counter }}">{{link}}</a></li> | |
4 | + <!--MODAL VIEW LINK--> | |
5 | + <div class="modal fade" id="linksModal{{slug}}{{ forloop.counter}}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> | |
6 | + <div class="modal-dialog" role="document"> | |
7 | + <div class="modal-content"> | |
8 | + <div class="modal-header"> | |
9 | + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
10 | + <h4 class="modal-title" id="myModalLabel">Link</h4> | |
11 | + </div> | |
12 | + <div class="modal-body"> | |
13 | + <!-- Card --> | |
14 | + <article class="card animated fadeInLeft"> | |
15 | + <div class="card-block"> | |
16 | + <b class="card-title">{{link.name}}</b><p></p> | |
17 | + <p class="card-text"> </p><p>{{link.link_description}}</p> | |
18 | + <a href="{{ link.link_url }}" class="btn btn-primary">Read more</a> | |
19 | + </div> | |
20 | + </article> | |
21 | + <!-- .end Card --> | |
22 | + </div> | |
23 | + </div> | |
24 | + </div> | |
25 | + </div> | |
26 | + <!-- EndModal --> | |
27 | +{% endfor %} | ... | ... |
... | ... | @@ -0,0 +1,31 @@ |
1 | +{% load static i18n list_topic_foruns permission_tags %} | |
2 | +{% for link in links%} | |
3 | + <li class="icon_edit_remove"> <a href="#" data-toggle="modal" data-target="#linksModalEdit"><i class="fa fa-pencil fa-lg" aria-hidden="true"></i></a> <a href="#" data-toggle="modal" data-target="#removeLink"><i class="fa fa-trash fa-lg" aria-hidden="true"></i></a></li> | |
4 | + <li><i class="fa fa-link" aria-hidden="true"></i> <a href="#" data-toggle="modal" data-target="#linksModal{{slug}}{{ forloop.counter }}">{{link}}</a></li> | |
5 | + | |
6 | + <!--MODAL VIEW LINK--> | |
7 | + <div class="modal fade" id="linksModal{{slug}}{{ forloop.counter}}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> | |
8 | + <div class="modal-dialog" role="document"> | |
9 | + <div class="modal-content"> | |
10 | + <div class="modal-header"> | |
11 | + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
12 | + <h4 class="modal-title" id="myModalLabel">Link</h4> | |
13 | + </div> | |
14 | + <div class="modal-body"> | |
15 | + <!-- Card --> | |
16 | + <article class="card animated fadeInLeft"> | |
17 | + <div class="card-block"> | |
18 | + <b class="card-title">{{link.name}}</b><p></p> | |
19 | + <p class="card-text"> </p><p>{{link.link_description}}</p> | |
20 | + <a href="{{ link.link_url }}" class="btn btn-primary">Read more</a> | |
21 | + </div> | |
22 | + </article> | |
23 | + <!-- .end Card --> | |
24 | + </div> | |
25 | + </div> | |
26 | + </div> | |
27 | + </div> | |
28 | + <!-- EndModal --> | |
29 | +{% endfor %} | |
30 | + <div class = "row" id="divModalLink"> | |
31 | + </div> | ... | ... |
... | ... | @@ -0,0 +1,12 @@ |
1 | +{% load static i18n permission_tags%} | |
2 | + | |
3 | + <div id="list-topic{{ topic.id }}-files"> | |
4 | + {% for file in files %} | |
5 | + <li id="file_{{ file.slug }}"><i class="material-icons">{{ file.file_type.icon }}</i> <a href="{{ file.file_url.url }}" target="_blank">{{ file.name }}</a></li> | |
6 | + {% endfor %} | |
7 | + </div> | |
8 | + | |
9 | + | |
10 | +<div class="row" id="divModalFile"> | |
11 | + | |
12 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,12 @@ |
1 | +{% load static i18n permission_tags%} | |
2 | + | |
3 | +<div id="list-topic-files-edit"> | |
4 | + {% for file in files %} | |
5 | + <li class="icon_edit_remove" id="file_edit_{{ file.slug }}"> <a href="javascript:get_modal_file('{% url 'course:file:update_file' file.slug %}', '#fileUpdateModal', '#divModalFileUpdate')" ><i class="fa fa-pencil fa-lg" aria-hidden="true"></i></a> <a href="javascript:get_modal_file('{% url 'course:file:delete_file' file.slug %}', '#fileDeleteModal', '#divModalFileUpdate')"><i class="fa fa-trash fa-lg" aria-hidden="true"></i></a></li> | |
6 | + <li id="file_edit_icon_{{ file.slug }}"><i class="material-icons">{{ file.file_type.icon }}</i> <a href="{{ file.file_url.url }}" target="_blank">{{ file.name }}</a></li> | |
7 | + {% endfor %} | |
8 | +</div> | |
9 | + | |
10 | +<div class="row" id="divModalFileUpdate"> | |
11 | + | |
12 | +</div> | |
0 | 13 | \ No newline at end of file | ... | ... |
courses/templatetags/list_topic_foruns.py
1 | 1 | from django import template |
2 | 2 | |
3 | +from links.models import Link | |
3 | 4 | from forum.models import Forum |
4 | 5 | from poll.models import Poll |
6 | +from files.models import TopicFile | |
5 | 7 | register = template.Library() |
6 | 8 | |
7 | 9 | """ |
... | ... | @@ -28,3 +30,43 @@ def list_topic_poll(request, topic): |
28 | 30 | context['topic'] = topic |
29 | 31 | |
30 | 32 | return context |
33 | + | |
34 | +@register.inclusion_tag('topic/list_file.html') | |
35 | +def list_topic_file(request, topic): | |
36 | + context = { | |
37 | + 'request': request, | |
38 | + } | |
39 | + | |
40 | + context['files'] = TopicFile.objects.filter(topic = topic) | |
41 | + context['topic'] = topic | |
42 | + | |
43 | + return context | |
44 | + | |
45 | +@register.inclusion_tag('topic/list_file_edit.html') | |
46 | +def list_topic_file_edit(request, topic): | |
47 | + context = { | |
48 | + 'request': request, | |
49 | + } | |
50 | + | |
51 | + context['files'] = TopicFile.objects.filter(topic = topic) | |
52 | + context['topic'] = topic | |
53 | + | |
54 | + return context | |
55 | + | |
56 | +@register.inclusion_tag('topic/link_topic_list_edit.html') | |
57 | +def list_topic_link_edit(request,topic): | |
58 | + context = { | |
59 | + 'request':request | |
60 | + } | |
61 | + context['links'] = Link.objects.filter(topic = topic) | |
62 | + context['slug'] = topic.slug | |
63 | + return context | |
64 | + | |
65 | +@register.inclusion_tag('topic/link_topic_list.html') | |
66 | +def list_topic_link(request,topic): | |
67 | + context = { | |
68 | + 'request':request | |
69 | + } | |
70 | + context['links'] = Link.objects.filter(topic = topic) | |
71 | + context['slug'] = topic.slug | |
72 | + return context | ... | ... |
courses/tests/test_topic.py
... | ... | @@ -85,7 +85,6 @@ class TopicTestCase(TestCase): |
85 | 85 | |
86 | 86 | def test_topic_update(self): |
87 | 87 | self.client.login(username='professor', password='testing') |
88 | - print (self.subject.topics.all()) | |
89 | 88 | url = reverse('course:update_topic',kwargs={'slug':self.subject.topics.all()[0].slug}) |
90 | 89 | data = { |
91 | 90 | "name": 'new name', | ... | ... |
courses/urls.py
... | ... | @@ -27,7 +27,10 @@ urlpatterns = [ |
27 | 27 | url(r'^subjects/categories$',views.IndexSubjectCategoryView.as_view(), name='subject_category_index'), |
28 | 28 | url(r'^forum/', include('forum.urls', namespace = 'forum')), |
29 | 29 | url(r'^poll/', include('poll.urls', namespace = 'poll')), |
30 | - url(r'^exam/', include('exam.urls', namespace = 'exam')), | |
30 | + # url(r'^exam/', include('exam.urls', namespace = 'exam')), | |
31 | + url(r'^files/', include('files.urls', namespace = 'file')), | |
32 | + url(r'^upload-material/$', views.UploadMaterialView.as_view(), name='upload_material'), | |
33 | + url(r'^links/',include('links.urls',namespace = 'links')), | |
31 | 34 | |
32 | 35 | |
33 | 36 | ... | ... |
courses/views.py
... | ... | @@ -13,10 +13,11 @@ from rolepermissions.verifications import has_object_permission |
13 | 13 | from django.http import HttpResponseRedirect |
14 | 14 | |
15 | 15 | from .forms import CourseForm, UpdateCourseForm, CategoryCourseForm, SubjectForm,TopicForm,ActivityForm |
16 | -from .models import Course, Subject, CourseCategory,Topic, SubjectCategory,Activity | |
16 | +from .models import Course, Subject, CourseCategory,Topic, SubjectCategory,Activity, CategorySubject | |
17 | 17 | from core.mixins import NotificationMixin |
18 | 18 | from users.models import User |
19 | 19 | from files.forms import FileForm |
20 | +from files.models import TopicFile | |
20 | 21 | |
21 | 22 | from datetime import date |
22 | 23 | |
... | ... | @@ -39,9 +40,9 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView): |
39 | 40 | else: |
40 | 41 | list_courses = Course.objects.filter(students__name = self.request.user.name) |
41 | 42 | categorys_courses = CourseCategory.objects.filter(course_category__students__name = self.request.user.name).distinct() |
42 | - | |
43 | + | |
43 | 44 | courses_category = Course.objects.filter(category__name = self.request.GET.get('category')) |
44 | - | |
45 | + | |
45 | 46 | none = None |
46 | 47 | q = self.request.GET.get('category', None) |
47 | 48 | if q is None: |
... | ... | @@ -57,7 +58,7 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView): |
57 | 58 | list_courses = paginator.page(1) |
58 | 59 | except EmptyPage: |
59 | 60 | list_courses = paginator.page(paginator.num_pages) |
60 | - | |
61 | + | |
61 | 62 | context['courses_category'] = courses_category |
62 | 63 | context['list_courses'] = list_courses |
63 | 64 | context['categorys_courses'] = categorys_courses |
... | ... | @@ -73,7 +74,6 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView): |
73 | 74 | object_list = Course.objects.filter(name__icontains = name) |
74 | 75 | else: |
75 | 76 | object_list = Course.objects.all() |
76 | - print(object_list) | |
77 | 77 | return object_list |
78 | 78 | |
79 | 79 | class CreateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edit.CreateView): |
... | ... | @@ -158,7 +158,6 @@ class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): |
158 | 158 | elif has_role(self.request.user,'professor'): |
159 | 159 | courses = self.request.user.courses.all() |
160 | 160 | context['courses'] = courses |
161 | - print (courses,"jdhksjbjs") | |
162 | 161 | context['title'] = course.name |
163 | 162 | |
164 | 163 | return context |
... | ... | @@ -191,6 +190,23 @@ class CourseView(LoginRequiredMixin, NotificationMixin, generic.DetailView): |
191 | 190 | courses = self.request.user.courses.all() |
192 | 191 | elif has_role(self.request.user, 'student'): |
193 | 192 | courses = self.request.user.courses_student.all() |
193 | + | |
194 | + categorys_subjects = None | |
195 | + if has_role(self.request.user,'professor') or has_role(self.request.user,'system_admin'): | |
196 | + categorys_subjects = CategorySubject.objects.filter(subject_category__professors__name = self.request.user.name).distinct() | |
197 | + else: | |
198 | + categorys_subjects = CategorySubject.objects.filter(subject_category__students__name = self.request.user.name).distinct() | |
199 | + | |
200 | + subjects_category = Subject.objects.filter(category__name = self.request.GET.get('category')) | |
201 | + | |
202 | + none = None | |
203 | + q = self.request.GET.get('category', None) | |
204 | + if q is None: | |
205 | + none = True | |
206 | + context['none'] = none | |
207 | + | |
208 | + context['subjects_category'] = subjects_category | |
209 | + context['categorys_subjects'] = categorys_subjects | |
194 | 210 | context['courses'] = courses |
195 | 211 | context['title'] = course.name |
196 | 212 | |
... | ... | @@ -300,14 +316,36 @@ class SubjectsView(LoginRequiredMixin, generic.ListView): |
300 | 316 | return context |
301 | 317 | |
302 | 318 | def get_context_data(self, **kwargs): |
303 | - subject = get_object_or_404(Subject, slug = self.kwargs.get('slug')) | |
319 | + | |
304 | 320 | context = super(SubjectsView, self).get_context_data(**kwargs) |
321 | + subject = get_object_or_404(Subject, slug = self.kwargs.get('slug')) | |
305 | 322 | context['course'] = subject.course |
306 | 323 | context['subject'] = subject |
307 | - context['form_file'] = FileForm | |
308 | 324 | context['topics'] = Topic.objects.filter(subject = subject) |
325 | + if has_role(self.request.user,'professor') or has_role(self.request.user,'system_admin'): | |
326 | + context['files'] = TopicFile.objects.filter(professor__name = self.request.user.name) | |
327 | + else: | |
328 | + context['files'] = TopicFile.objects.filter(students__name = self.request.user.name) | |
329 | + return context | |
330 | + | |
331 | +class UploadMaterialView(LoginRequiredMixin, generic.edit.CreateView): | |
332 | + login_url = reverse_lazy("core:home") | |
333 | + redirect_field_name = 'next' | |
334 | + | |
335 | + template_name = 'files/create_file.html' | |
336 | + form_class = FileForm | |
337 | + | |
338 | + def form_invalid(self, form): | |
339 | + context = super(UploadMaterialView, self).form_invalid(form) | |
340 | + context.status_code = 400 | |
341 | + | |
309 | 342 | return context |
310 | 343 | |
344 | + def get_success_url(self): | |
345 | + self.success_url = reverse('course:view_subject', args = (self.object.slug, )) | |
346 | + | |
347 | + return self.success_url | |
348 | + | |
311 | 349 | class TopicsView(LoginRequiredMixin, generic.ListView): |
312 | 350 | |
313 | 351 | login_url = reverse_lazy("core:home") | ... | ... |
exam/migrations/0001_initial.py
1 | 1 | # -*- coding: utf-8 -*- |
2 | -# Generated by Django 1.10 on 2016-10-06 19:57 | |
2 | +# Generated by Django 1.10 on 2016-10-18 20:26 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | 5 | from django.db import migrations, models |
... | ... | @@ -11,6 +11,7 @@ class Migration(migrations.Migration): |
11 | 11 | initial = True |
12 | 12 | |
13 | 13 | dependencies = [ |
14 | + ('courses', '0001_initial'), | |
14 | 15 | ] |
15 | 16 | |
16 | 17 | operations = [ |
... | ... | @@ -18,27 +19,26 @@ class Migration(migrations.Migration): |
18 | 19 | name='Answer', |
19 | 20 | fields=[ |
20 | 21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
21 | - ('answer', models.CharField(max_length=200, verbose_name='Answer')), | |
22 | + ('answer', models.CharField(max_length=300, verbose_name='Answer')), | |
22 | 23 | ('order', models.PositiveSmallIntegerField(verbose_name='Order')), |
23 | 24 | ], |
24 | 25 | options={ |
26 | + 'verbose_name': 'Answer', | |
25 | 27 | 'verbose_name_plural': 'Answers', |
26 | 28 | 'ordering': ('order',), |
27 | - 'verbose_name': 'Answer', | |
28 | 29 | }, |
29 | 30 | ), |
30 | 31 | migrations.CreateModel( |
31 | 32 | name='Exam', |
32 | 33 | fields=[ |
33 | - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
34 | - ('name', models.CharField(max_length=100, verbose_name='Name')), | |
35 | - ('beginDate', models.DateTimeField(auto_now_add=True, verbose_name='Start Date')), | |
36 | - ('endDate', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), | |
34 | + ('activity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Activity')), | |
35 | + ('begin_date', models.DateField(blank=True, verbose_name='Begin of Course Date')), | |
37 | 36 | ], |
38 | 37 | options={ |
39 | - 'verbose_name_plural': 'Exams', | |
40 | 38 | 'verbose_name': 'Exam', |
39 | + 'verbose_name_plural': 'Exams', | |
41 | 40 | }, |
41 | + bases=('courses.activity',), | |
42 | 42 | ), |
43 | 43 | migrations.AddField( |
44 | 44 | model_name='answer', | ... | ... |
exam/migrations/0002_auto_20161013_2047.py
... | ... | @@ -1,50 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-13 23:47 | |
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 | - ('courses', '0005_file'), | |
13 | - ('exam', '0001_initial'), | |
14 | - ] | |
15 | - | |
16 | - operations = [ | |
17 | - migrations.RemoveField( | |
18 | - model_name='exam', | |
19 | - name='beginDate', | |
20 | - ), | |
21 | - migrations.RemoveField( | |
22 | - model_name='exam', | |
23 | - name='endDate', | |
24 | - ), | |
25 | - migrations.RemoveField( | |
26 | - model_name='exam', | |
27 | - name='id', | |
28 | - ), | |
29 | - migrations.RemoveField( | |
30 | - model_name='exam', | |
31 | - name='name', | |
32 | - ), | |
33 | - migrations.AddField( | |
34 | - model_name='exam', | |
35 | - name='activity_ptr', | |
36 | - field=models.OneToOneField(auto_created=True, default=None, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Activity'), | |
37 | - preserve_default=False, | |
38 | - ), | |
39 | - migrations.AddField( | |
40 | - model_name='exam', | |
41 | - name='begin_date', | |
42 | - field=models.DateField(default=None, verbose_name='Begin of Course Date'), | |
43 | - preserve_default=False, | |
44 | - ), | |
45 | - migrations.AlterField( | |
46 | - model_name='answer', | |
47 | - name='answer', | |
48 | - field=models.CharField(max_length=300, verbose_name='Answer'), | |
49 | - ), | |
50 | - ] |
exam/models.py
... | ... | @@ -6,7 +6,7 @@ from core.models import Resource |
6 | 6 | from courses.models import Activity |
7 | 7 | |
8 | 8 | class Exam(Activity): |
9 | - begin_date = models.DateField(_('Begin of Course Date')) | |
9 | + begin_date = models.DateField(_('Begin of Course Date'), blank=True) | |
10 | 10 | |
11 | 11 | class Meta: |
12 | 12 | verbose_name = _('Exam') | ... | ... |
exam/urls.py
1 | -from django.conf.urls import url | |
2 | - | |
3 | -from . import views | |
4 | - | |
5 | -urlpatterns = [ | |
6 | - url(r'^create/(?P<slug>[\w\-_]+)/$', views.CreateExam.as_view(), name='create_exam'), # exam slug | |
7 | - url(r'^update/(?P<slug>[\w\-_]+)/$', views.UpdateExam.as_view(), name='update_exam'), # topic slug | |
8 | - url(r'^view/(?P<slug>[\w\-_]+)/$', views.ViewExam.as_view(), name='view_exam'), # exam slug | |
9 | - url(r'^delete/(?P<slug>[\w\-_]+)/$', views.DeleteExam.as_view(), name='delete_exam'), # exam | |
10 | - url(r'^answer/$', views.AnswerExam.as_view(), name='answer_exam'), # exam | |
11 | - url(r'^answer-exam/(?P<slug>[\w\-_]+)/$', views.AnswerStudentExam.as_view(), name='answer_student_exam'), # exam slug | |
12 | -] | |
1 | +# from django.conf.urls import url | |
2 | +# | |
3 | +# from . import views | |
4 | +# | |
5 | +# urlpatterns = [ | |
6 | +# url(r'^create/(?P<slug>[\w\-_]+)/$', views.CreateExam.as_view(), name='create_exam'), # exam slug | |
7 | +# url(r'^update/(?P<slug>[\w\-_]+)/$', views.UpdateExam.as_view(), name='update_exam'), # topic slug | |
8 | +# url(r'^view/(?P<slug>[\w\-_]+)/$', views.ViewExam.as_view(), name='view_exam'), # exam slug | |
9 | +# url(r'^delete/(?P<slug>[\w\-_]+)/$', views.DeleteExam.as_view(), name='delete_exam'), # exam | |
10 | +# url(r'^answer/$', views.AnswerExam.as_view(), name='answer_exam'), # exam | |
11 | +# url(r'^answer-exam/(?P<slug>[\w\-_]+)/$', views.AnswerStudentExam.as_view(), name='answer_student_exam'), # exam slug | |
12 | +# ] | ... | ... |
exam/views.py
... | ... | @@ -33,6 +33,7 @@ class ViewExam(LoginRequiredMixin,generic.DetailView): |
33 | 33 | context['course'] = exam.topic.subject.course |
34 | 34 | context['subject'] = exam.topic.subject |
35 | 35 | context['subjects'] = exam.topic.subject.course.subjects.all() |
36 | + | |
36 | 37 | answered = AnswersStudent.objects.filter(exam = exam, student=self.request.user) |
37 | 38 | print (answered) |
38 | 39 | if answered.count()<1: |
... | ... | @@ -145,7 +146,6 @@ class UpdateExam(LoginRequiredMixin,HasRoleMixin,generic.UpdateView): |
145 | 146 | |
146 | 147 | answers = {} |
147 | 148 | for answer in exam.answers.all(): |
148 | - # print (key.answer) | |
149 | 149 | answers[answer.order] = answer.answer |
150 | 150 | |
151 | 151 | keys = sorted(answers) | ... | ... |
files/admin.py
files/forms.py
1 | +from django.conf import settings | |
1 | 2 | from django import forms |
2 | 3 | from .models import TopicFile |
4 | +from django.core.exceptions import ValidationError, FieldError | |
3 | 5 | from django.utils.translation import ugettext_lazy as _ |
4 | 6 | |
5 | 7 | class FileForm(forms.ModelForm): |
6 | 8 | |
9 | + def clean_file_url(self): | |
10 | + file_url = self.cleaned_data['file_url'] | |
11 | + if file_url._size > settings.MAX_UPLOAD_SIZE: | |
12 | + raise forms.ValidationError(_('File too large (Max 10MB)')) | |
13 | + return file_url | |
14 | + | |
15 | + | |
16 | + class Meta: | |
17 | + model = TopicFile | |
18 | + fields = ['name', 'file_url'] | |
19 | + | |
20 | +class UpdateFileForm(forms.ModelForm): | |
21 | + file_url = forms.FileField(required=False) | |
22 | + | |
23 | + def clean_file_url(self): | |
24 | + file_url = self.cleaned_data['file_url'] | |
25 | + print(file_url) | |
26 | + if file_url: | |
27 | + if hasattr(file_url, '_size'): | |
28 | + if file_url._size > settings.MAX_UPLOAD_SIZE: | |
29 | + raise forms.ValidationError(_('File too large (Max 10MB)')) | |
30 | + return file_url | |
31 | + | |
32 | + | |
7 | 33 | class Meta: |
8 | 34 | model = TopicFile |
9 | 35 | fields = ['name', 'file_url'] |
10 | 36 | \ No newline at end of file | ... | ... |
files/migrations/0001_initial.py
1 | 1 | # -*- coding: utf-8 -*- |
2 | -# Generated by Django 1.10 on 2016-10-13 16:12 | |
2 | +# Generated by Django 1.10 on 2016-10-18 20:26 | |
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', '0002_mymetype'), | |
16 | - ('courses', '0004_auto_20161011_1951'), | |
15 | + ('core', '0001_initial'), | |
16 | + ('courses', '0001_initial'), | |
17 | 17 | ] |
18 | 18 | |
19 | 19 | operations = [ |
... | ... | @@ -23,11 +23,12 @@ class Migration(migrations.Migration): |
23 | 23 | ('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')), |
24 | 24 | ('description', models.TextField(blank=True, verbose_name='Description')), |
25 | 25 | ('file_url', models.FileField(upload_to=files.models.file_path, verbose_name='File')), |
26 | - ('file_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='topic_files', to='core.MymeType', verbose_name='Type file')), | |
26 | + ('file_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='topic_files', to='core.MimeType', verbose_name='Type file')), | |
27 | 27 | ], |
28 | 28 | options={ |
29 | 29 | 'verbose_name': 'File', |
30 | 30 | 'verbose_name_plural': 'Files', |
31 | + 'ordering': ('-id',), | |
31 | 32 | }, |
32 | 33 | bases=('courses.material',), |
33 | 34 | ), | ... | ... |
... | ... | @@ -0,0 +1,24 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Generated by Django 1.10 on 2016-10-18 20:26 | |
3 | +from __future__ import unicode_literals | |
4 | + | |
5 | +from django.conf import settings | |
6 | +from django.db import migrations, models | |
7 | + | |
8 | + | |
9 | +class Migration(migrations.Migration): | |
10 | + | |
11 | + initial = True | |
12 | + | |
13 | + dependencies = [ | |
14 | + ('files', '0001_initial'), | |
15 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
16 | + ] | |
17 | + | |
18 | + operations = [ | |
19 | + migrations.AddField( | |
20 | + model_name='topicfile', | |
21 | + name='professor', | |
22 | + field=models.ManyToManyField(related_name='file_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors'), | |
23 | + ), | |
24 | + ] | ... | ... |
files/models.py
1 | 1 | from django.db import models |
2 | 2 | from django.utils.translation import ugettext_lazy as _ |
3 | -from core.models import MymeType | |
3 | +from core.models import MimeType | |
4 | 4 | from courses.models import Material |
5 | +from users.models import User | |
5 | 6 | |
6 | 7 | """ |
7 | 8 | Function to return the path where the file should be saved |
... | ... | @@ -15,14 +16,17 @@ def file_path(instance, filename): |
15 | 16 | It's like a support material for the students. |
16 | 17 | """ |
17 | 18 | class TopicFile(Material): |
19 | + | |
20 | + professor = models.ManyToManyField(User,verbose_name=_('Professors'), related_name='file_professors') | |
18 | 21 | description = models.TextField(_('Description'), blank=True) |
19 | 22 | file_url = models.FileField(verbose_name = _("File"), upload_to = file_path) |
20 | - file_type = models.ForeignKey(MymeType, verbose_name=_('Type file'), related_name='topic_files') | |
23 | + file_type = models.ForeignKey(MimeType, verbose_name=_('Type file'), related_name='topic_files') | |
21 | 24 | |
22 | 25 | |
23 | 26 | class Meta: |
24 | 27 | verbose_name = _("File") |
25 | 28 | verbose_name_plural = _("Files") |
29 | + ordering = ('-id',) | |
26 | 30 | |
27 | 31 | def __str__(self): |
28 | 32 | return self.name |
29 | 33 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,63 @@ |
1 | +function get_modal_file(url, id, div_content){ | |
2 | + | |
3 | + $.get(url, function (data) { | |
4 | + $(div_content).empty(); | |
5 | + $(div_content).append(data); | |
6 | + $(id).modal('show'); | |
7 | + }); | |
8 | + | |
9 | +} | |
10 | + | |
11 | +// $(document).ready(function (){ | |
12 | +// // alert('Oi'); | |
13 | +// var frm = $("#form-file"); | |
14 | +// frm.submit(function(event) { | |
15 | +// $.ajax({ | |
16 | +// type: frm.attr('method'), | |
17 | +// url: frm.attr('action'), | |
18 | +// data: { | |
19 | +// 'file_url': $('#id_file_url'), | |
20 | +// 'name': $('#id_name'), | |
21 | +// csrfmiddlewaretoken: csrf | |
22 | +// }, | |
23 | +// success: function (data) { | |
24 | +// alert(data); | |
25 | +// // $("#posts_list").append(data); | |
26 | +// // frm[0].reset(); | |
27 | +// }, | |
28 | +// processData : false, | |
29 | +// error: function(data) { | |
30 | +// alert('Error'); | |
31 | +// // console.log(frm.serialize()); | |
32 | +// // console.log('Error'); | |
33 | +// } | |
34 | +// }); | |
35 | +// $('#fileModal').modal('hide'); | |
36 | +// event.preventDefault(); | |
37 | +// }); | |
38 | +// }); | |
39 | + | |
40 | +// var Submite = { | |
41 | +// post: function(url,dados){ | |
42 | +// $('#fileModal').modal('hide'); | |
43 | +// $.post(url,dados, function(data){ | |
44 | +// }).fail(function(data){ | |
45 | +// $("div.modal-backdrop.fade.in").remove(); | |
46 | +// $("#modal_poll").empty(); | |
47 | +// $("#modal_poll").append(data.responseText); | |
48 | +// }); | |
49 | +// } | |
50 | +// , | |
51 | +// remove: function(url,dados, id_li_link){ | |
52 | +// $('#fileModal').modal('hide'); | |
53 | +// $.post(url,dados, function(data){ | |
54 | +// $(id_li_link).remove(); | |
55 | +// $("#modal_poll").empty(); | |
56 | +// $("div.modal-backdrop.fade.in").remove(); | |
57 | +// }).fail(function(){ | |
58 | +// $("#modal_poll").empty(); | |
59 | +// $("#modal_poll").append(data); | |
60 | +// $('#fileModal').modal('show'); | |
61 | +// }); | |
62 | +// } | |
63 | +// } | |
0 | 64 | \ No newline at end of file | ... | ... |
files/templates/files/create_file.html
1 | -{% load widget_tweaks i18n %} | |
1 | +{% load static widget_tweaks i18n %} | |
2 | + | |
2 | 3 | <!-- MODAL CREATE FILE --> |
3 | -<div class="modal fade" id="createFileModal" tabindex="-1" role="dialog" aria-labelledby="createFileLabel" style="display: none;"> | |
4 | - <div class="modal-dialog" role="document"> | |
5 | - <div class="modal-content"> | |
6 | - <div class="modal-header"> | |
7 | - <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
8 | - <h4 class="modal-title" id="createFileLabel">{% trans 'Add File' %}</h4> | |
9 | - </div> | |
10 | - <div class="modal-body"> | |
11 | - <!-- Card --> | |
12 | - <form class="form-horizontal"> | |
13 | - {% csrf_token %} | |
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">×</span> | |
19 | - </button> | |
20 | - <p>{{ message }}</p> | |
21 | - </div> | |
22 | - {% endfor %} | |
23 | - {% endif %} | |
24 | - <fieldset> | |
25 | - {% for field in form_file %} | |
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_url' %} | |
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> | |
40 | - </button> | |
41 | - </span> | |
4 | +<div class="erro"> | |
5 | + <div class="modal fade" id="fileModal" tabindex="-1" role="dialog" aria-labelledby="createFileLabel"> | |
6 | + <div class="modal-dialog" role="document"> | |
7 | + <div class="modal-content"> | |
8 | + <div class="modal-header"> | |
9 | + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
10 | + <h4 class="modal-title" id="createFileLabel">{% trans 'Add File' %}</h4> | |
11 | + </div> | |
12 | + <div class="modal-body"> | |
13 | + <!-- Card --> | |
14 | + <form class="form-horizontal" method="post" id="form-file" enctype="multipart/form-data"> | |
15 | + {% csrf_token %} | |
16 | + {% if messages %} | |
17 | + {% for message in messages %} | |
18 | + <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert"> | |
19 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
20 | + <span aria-hidden="true">×</span> | |
21 | + </button> | |
22 | + <p>{{ message }}</p> | |
23 | + </div> | |
24 | + {% endfor %} | |
25 | + {% endif %} | |
26 | + <fieldset> | |
27 | + {% for field in form %} | |
28 | + <div class="form-group is-empy{% if form.has_error %} has-error {% endif %} is-fileinput"> | |
29 | + <div class="col-md-12"> | |
30 | + {% if field.field.required %} | |
31 | + <label for="{{ field.auto_id }}" class="control-label">{{ field.label }}<span>*</span></label> | |
32 | + {% else %} | |
33 | + <label for="{{ field.auto_id }}" class=" control-label">{{ field.label }}</label> | |
34 | + {% endif %} | |
35 | + {% if field.auto_id == 'id_file_url' %} | |
36 | + {% render_field field class='form-control input-sm' %} | |
37 | + <div class="input-group"> | |
38 | + <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your file...' %}"> | |
39 | + <span class="input-group-btn input-group-sm"> | |
40 | + <button type="button" class="btn btn-fab btn-fab-mini"> | |
41 | + <i class="material-icons">attach_file</i> | |
42 | + </button> | |
43 | + </span> | |
44 | + </div> | |
45 | + {% else %} | |
46 | + {% render_field field class='form-control input-sm' %} | |
47 | + <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
48 | + {% endif %} | |
49 | + </div> | |
50 | + | |
51 | + {% if field.errors %} | |
52 | + <div class="alert alert-danger alert-dismissible clearfix" role="alert"> | |
53 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
54 | + <span aria-hidden="true">×</span> | |
55 | + </button> | |
56 | + <ul> | |
57 | + {% for error in field.errors %} | |
58 | + <li>{{ error }}</li> | |
59 | + {% endfor %} | |
60 | + </ul> | |
42 | 61 | </div> |
43 | - {% else %} | |
44 | - {% render_field field class='form-control input-sm' %} | |
45 | - <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
46 | 62 | {% endif %} |
47 | 63 | </div> |
48 | - | |
49 | - {% if field.errors %} | |
50 | - <div class="alert alert-danger alert-dismissible" role="alert"> | |
51 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
52 | - <span aria-hidden="true">×</span> | |
53 | - </button> | |
54 | - <ul> | |
55 | - {% for error in field.errors %} | |
56 | - <li>{{ error }}</li> | |
57 | - {% endfor %} | |
58 | - </ul> | |
59 | - </div> | |
60 | - {% endif %} | |
61 | - </div> | |
62 | - {% endfor %} | |
64 | + {% endfor %} | |
63 | 65 | |
64 | - <div class="form-group"> | |
65 | - <div class="col-md-12 text-center"> | |
66 | - <p><b>The file size shouldn't exceed 10MB</b></p> | |
66 | + <div class="form-group"> | |
67 | + <div class="col-md-12 text-center"> | |
68 | + <p><b>The file size shouldn't exceed 10MB</b></p> | |
69 | + </div> | |
67 | 70 | </div> |
68 | - </div> | |
69 | 71 | |
70 | - <div class="form-group"> | |
71 | - <div class="col-md-12"> | |
72 | - <a href="javascript:void(0)" class="btn btn-raised btn-default">Cancel<div class="ripple-container"></div></a> | |
73 | - <a href="javascript:void(0)" class="btn btn-raised btn-primary">Submit</a> | |
72 | + <div class="form-group"> | |
73 | + <div class="col-md-12"> | |
74 | + <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button> | |
75 | + <button class="btn btn-raised btn-primary" type="submit">Submit</button> | |
76 | + </div> | |
74 | 77 | </div> |
75 | - </div> | |
76 | - </fieldset> | |
77 | - </form> | |
78 | - <!-- .end Card --> | |
79 | - </div> | |
78 | + </fieldset> | |
79 | + </form> | |
80 | + <!-- .end Card --> | |
81 | + </div> | |
82 | + </div> | |
80 | 83 | </div> |
81 | 84 | </div> |
82 | 85 | </div> |
83 | -<!-- EndModal --> | |
84 | 86 | \ No newline at end of file |
87 | + | |
88 | +{% block script_file %} | |
89 | + | |
90 | + {# // <script src="{% static 'js/file.js' %}"></script> #} | |
91 | + <script type="text/javascript"> | |
92 | + $("#form-file").submit(function(event) { | |
93 | + var data = new FormData($('#form-file').get(0)); | |
94 | + $.ajax({ | |
95 | + url: "{% url 'course:file:create_file' topic.slug %}", | |
96 | + type: $("#form-file").attr('method'), | |
97 | + data: data, | |
98 | + cache: false, | |
99 | + processData: false, | |
100 | + contentType: false, | |
101 | + success: function(data) { | |
102 | + $('#fileModal').modal('hide'); | |
103 | + alert(data); | |
104 | + // $('#list-topic-files').append(data); | |
105 | + }, | |
106 | + error: function(data){ | |
107 | + $('.erro').html(data.responseText); | |
108 | + $('.modal-backdrop').remove(); | |
109 | + $('#fileModal').modal(); | |
110 | + } | |
111 | + }); | |
112 | + event.preventDefault(); | |
113 | + }); | |
114 | + </script> | |
115 | +{% endblock script_file %} | |
85 | 116 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,76 @@ |
1 | +{% load static widget_tweaks i18n %} | |
2 | + | |
3 | +<!-- MODAL CREATE FILE --> | |
4 | +<link rel="stylesheet" type="text/css" href="{% static 'css/file.css' %}"> | |
5 | + | |
6 | +<div class="erro-update"> | |
7 | + <div class="modal fade" id="fileDeleteModal" tabindex="-1" role="dialog" aria-labelledby="deleteFileLabel" style="z-index: 10"> | |
8 | + <div class="modal-dialog" role="document"> | |
9 | + <div class="modal-content"> | |
10 | + <div class="modal-header"> | |
11 | + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
12 | + <h4 class="modal-title" id="deleteFileLabel">{% trans 'Delete File' %}</h4> | |
13 | + </div> | |
14 | + <div class="modal-body"> | |
15 | + <!-- Card --> | |
16 | + <form class="form-horizontal" method="post" id="form-delete-file" enctype="multipart/form-data"> | |
17 | + {% csrf_token %} | |
18 | + {% if messages %} | |
19 | + {% for message in messages %} | |
20 | + <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert"> | |
21 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
22 | + <span aria-hidden="true">×</span> | |
23 | + </button> | |
24 | + <p>{{ message }}</p> | |
25 | + </div> | |
26 | + {% endfor %} | |
27 | + {% endif %} | |
28 | + <fieldset> | |
29 | + <div class="col-md-12"> | |
30 | + {% trans "Are you sure to delete " %}<a href="{{ file.file_url.url }}" target="_blank" > {{ file.name }} </a> of {{ file.topic.name }}? | |
31 | + </div> | |
32 | + <div class="form-group"> | |
33 | + <div class="col-md-12"> | |
34 | + <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button> | |
35 | + <button class="btn btn-raised btn-primary" type="submit">Delete</button> | |
36 | + </div> | |
37 | + </div> | |
38 | + </fieldset> | |
39 | + </form> | |
40 | + <!-- .end Card --> | |
41 | + </div> | |
42 | + </div> | |
43 | + </div> | |
44 | + </div> | |
45 | +</div> | |
46 | + | |
47 | +{% block script_file %} | |
48 | + | |
49 | + {# // <script src="{% static 'js/file.js' %}"></script> #} | |
50 | + <script type="text/javascript"> | |
51 | + $("#form-delete-file").submit(function(event) { | |
52 | + var data = new FormData($('#form-delete-file').get(0)); | |
53 | + $.ajax({ | |
54 | + url: "{% url 'course:file:delete_file' file.slug %}", | |
55 | + type: $("#form-delete-file").attr('method'), | |
56 | + data: data, | |
57 | + cache: false, | |
58 | + processData: false, | |
59 | + contentType: false, | |
60 | + success: function(data) { | |
61 | + $('#fileDeleteModal').modal('hide'); | |
62 | + $('#file_eidt_{{ file.slug }}').remove(); | |
63 | + $('#file_eidt_icon_{{ file.slug }}').remove(); | |
64 | + }, | |
65 | + error: function(data){ | |
66 | + // $('.erro-update').html(data.responseText); | |
67 | + $('.modal-backdrop').remove(); | |
68 | + $('#fileDeteleModal').modal(); | |
69 | + alert('Erro'); | |
70 | + } | |
71 | + }); | |
72 | + event.preventDefault(); | |
73 | + }); | |
74 | + </script> | |
75 | +{% endblock script_file %} | |
76 | +<!-- EndModal --> | |
0 | 77 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,120 @@ |
1 | +{% load static widget_tweaks i18n %} | |
2 | + | |
3 | +<!-- MODAL CREATE FILE --> | |
4 | +<link rel="stylesheet" type="text/css" href="{% static 'css/file.css' %}"> | |
5 | + | |
6 | +<div class="erro-update"> | |
7 | + <div class="modal fade" id="fileUpdateModal" tabindex="-1" role="dialog" aria-labelledby="updateFileLabel" style="z-index: 10"> | |
8 | + <div class="modal-dialog" role="document"> | |
9 | + <div class="modal-content"> | |
10 | + <div class="modal-header"> | |
11 | + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
12 | + <h4 class="modal-title" id="updateFileLabel">{% trans 'Edit File' %}</h4> | |
13 | + </div> | |
14 | + <div class="modal-body"> | |
15 | + <!-- Card --> | |
16 | + <form class="form-horizontal" method="post" id="form-update-file" enctype="multipart/form-data"> | |
17 | + {% csrf_token %} | |
18 | + {% if messages %} | |
19 | + {% for message in messages %} | |
20 | + <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert"> | |
21 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
22 | + <span aria-hidden="true">×</span> | |
23 | + </button> | |
24 | + <p>{{ message }}</p> | |
25 | + </div> | |
26 | + {% endfor %} | |
27 | + {% endif %} | |
28 | + <fieldset> | |
29 | + {% for field in form %} | |
30 | + <div class="form-group is-empy{% if form.has_error %} has-error {% endif %} is-fileinput"> | |
31 | + <div class="col-md-12"> | |
32 | + {% if field.field.required %} | |
33 | + <label for="{{ field.auto_id }}" class="control-label">{{ field.label }}<span>*</span></label> | |
34 | + {% else %} | |
35 | + <label for="{{ field.auto_id }}" class=" control-label">{{ field.label }}</label> | |
36 | + {% endif %} | |
37 | + {% if field.auto_id == 'id_file_url' %} | |
38 | + <input class="form-control input-sm" id="id_file_url" name="file_url" type="file"> | |
39 | + <div class="input-group"> | |
40 | + <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your file...' %}"> | |
41 | + <span class="input-group-btn input-group-sm"> | |
42 | + <button type="button" class="btn btn-fab btn-fab-mini"> | |
43 | + <i class="material-icons">attach_file</i> | |
44 | + </button> | |
45 | + </span> | |
46 | + </div> | |
47 | + <div class="crearfix"> | |
48 | + <a href="{{ file.file_url.url }}" target="_blank">{% trans "See current file" %}</a> | |
49 | + </div> | |
50 | + {% else %} | |
51 | + {% render_field field class='form-control input-sm' %} | |
52 | + <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
53 | + {% endif %} | |
54 | + </div> | |
55 | + | |
56 | + {% if field.errors %} | |
57 | + <div class="alert alert-danger alert-dismissible clearfix" role="alert"> | |
58 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
59 | + <span aria-hidden="true">×</span> | |
60 | + </button> | |
61 | + <ul> | |
62 | + {% for error in field.errors %} | |
63 | + <li>{{ error }}</li> | |
64 | + {% endfor %} | |
65 | + </ul> | |
66 | + </div> | |
67 | + {% endif %} | |
68 | + </div> | |
69 | + {% endfor %} | |
70 | + | |
71 | + <div class="form-group"> | |
72 | + <div class="col-md-12 text-center"> | |
73 | + <p><b>The file size shouldn't exceed 10MB</b></p> | |
74 | + </div> | |
75 | + </div> | |
76 | + | |
77 | + <div class="form-group"> | |
78 | + <div class="col-md-12"> | |
79 | + <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button> | |
80 | + <button class="btn btn-raised btn-primary" type="submit">Submit</button> | |
81 | + </div> | |
82 | + </div> | |
83 | + </fieldset> | |
84 | + </form> | |
85 | + <!-- .end Card --> | |
86 | + </div> | |
87 | + </div> | |
88 | + </div> | |
89 | + </div> | |
90 | +</div> | |
91 | + | |
92 | +{% block script_file %} | |
93 | + | |
94 | + {# // <script src="{% static 'js/file.js' %}"></script> #} | |
95 | + <script type="text/javascript"> | |
96 | + $("#form-update-file").submit(function(event) { | |
97 | + var data = new FormData($('#form-update-file').get(0)); | |
98 | + $.ajax({ | |
99 | + url: "{% url 'course:file:update_file' file.slug %}", | |
100 | + type: $("#form-update-file").attr('method'), | |
101 | + data: data, | |
102 | + cache: false, | |
103 | + processData: false, | |
104 | + contentType: false, | |
105 | + success: function(data) { | |
106 | + $('#fileUpdateModal').modal('hide'); | |
107 | + alert(data); | |
108 | + // $('#list-topic-files').append(data); | |
109 | + }, | |
110 | + error: function(data){ | |
111 | + $('.erro-update').html(data.responseText); | |
112 | + $('.modal-backdrop').remove(); | |
113 | + $('#fileUpdateModal').modal(); | |
114 | + } | |
115 | + }); | |
116 | + event.preventDefault(); | |
117 | + }); | |
118 | + </script> | |
119 | +{% endblock script_file %} | |
120 | +<!-- EndModal --> | |
0 | 121 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +from django.conf.urls import url, include | |
2 | + | |
3 | +from . import views | |
4 | + | |
5 | +urlpatterns = [ | |
6 | + url(r'^create/(?P<slug>[\w_-]+)/$', views.CreateFile.as_view(), name='create_file'), # topic slug | |
7 | + url(r'^update/(?P<slug>[\w_-]+)/$', views.UpdateFile.as_view(), name='update_file'), # file slug | |
8 | + url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteFile.as_view(), name='delete_file'), # file slug | |
9 | + url(r'^render-file/(?P<id>[0-9]+)/$', views.render_file, name='render_file'), # file slug | |
10 | + | |
11 | +] | |
0 | 12 | \ No newline at end of file | ... | ... |
files/views.py
1 | -from django.shortcuts import render | |
1 | +from django.shortcuts import render, get_object_or_404, redirect | |
2 | +from django.conf import settings | |
3 | +from django.views import generic | |
4 | +from django.contrib import messages | |
5 | +from django.core.urlresolvers import reverse_lazy | |
6 | +from django.contrib.auth.mixins import LoginRequiredMixin | |
7 | +from rolepermissions.mixins import HasRoleMixin | |
8 | +from .forms import FileForm, UpdateFileForm | |
9 | +from .models import TopicFile | |
10 | +from .utils import mime_type_to_material_icons | |
11 | +from courses.models import Topic | |
12 | +from core.models import MimeType | |
2 | 13 | |
3 | 14 | # Create your views here. |
15 | +class CreateFile(LoginRequiredMixin, HasRoleMixin, generic.edit.CreateView): | |
16 | + allowed_roles = ['professor', 'system_admin'] | |
17 | + login_url = reverse_lazy("core:home") | |
18 | + redirect_field_name = 'next' | |
19 | + model = TopicFile | |
20 | + template_name = 'files/create_file.html' | |
21 | + form_class = FileForm | |
22 | + success_url = reverse_lazy('course:file:render_file') | |
23 | + | |
24 | + def form_invalid(self, form, **kwargs): | |
25 | + context = super(CreateFile, self).form_invalid(form) | |
26 | + context.status_code = 400 | |
27 | + | |
28 | + return context | |
29 | + | |
30 | + def form_valid(self, form): | |
31 | + self.object = form.save(commit = False) | |
32 | + topic = get_object_or_404(Topic, slug = self.kwargs.get('slug')) | |
33 | + self.object.topic = topic | |
34 | + # Set MimeType | |
35 | + file = self.request.FILES['file_url'] | |
36 | + try: | |
37 | + if file: | |
38 | + file_type = file.content_type | |
39 | + | |
40 | + # Check if exist a mimetype in database | |
41 | + try: | |
42 | + self.object.file_type = MimeType.objects.get(typ = file_type) | |
43 | + # Create if not | |
44 | + except: | |
45 | + mtype = MimeType.objects.create( | |
46 | + typ = file_type, | |
47 | + icon = mime_type_to_material_icons[file_type] | |
48 | + ) | |
49 | + mtype.save() | |
50 | + self.object.file_type = mtype | |
51 | + except: | |
52 | + print('File not uploaded') | |
53 | + # self.object.file_type = MimeType.objects.get(id = 1) | |
54 | + | |
55 | + self.object.save() | |
56 | + | |
57 | + return self.render_to_response(self.get_context_data(form = form), status = 200) | |
58 | + | |
59 | + def get_context_data(self, **kwargs): | |
60 | + context = super(CreateFile, self).get_context_data(**kwargs) | |
61 | + topic = get_object_or_404(Topic, slug = self.kwargs.get('slug')) | |
62 | + context["topic"] = topic | |
63 | + context['subject'] = topic.subject | |
64 | + context['subjects'] = topic.subject.course.subjects.all() | |
65 | + try: | |
66 | + context['latest_file'] = TopicFile.objects.latest('id') | |
67 | + except: | |
68 | + pass | |
69 | + return context | |
70 | + | |
71 | + def get_success_url(self): | |
72 | + self.success_url = reverse('course:file:render_file', args = (self.object.id, )) | |
73 | + | |
74 | + return self.success_url | |
75 | + | |
76 | +def render_file(request, id): | |
77 | + template_name = 'files/render_file.html' | |
78 | + context = { | |
79 | + 'file': get_object_or_404(TopicFile, id = id) | |
80 | + } | |
81 | + return render(request, template_name, context) | |
82 | + | |
83 | + | |
84 | +class UpdateFile(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): | |
85 | + allowed_roles = ['professor', 'system_admin'] | |
86 | + login_url = reverse_lazy("core:home") | |
87 | + redirect_field_name = 'next' | |
88 | + model = TopicFile | |
89 | + template_name = 'files/update_file.html' | |
90 | + form_class = UpdateFileForm | |
91 | + context_object_name = 'file' | |
92 | + success_url = reverse_lazy('course:file:render_file') | |
93 | + | |
94 | + def form_invalid(self, form, **kwargs): | |
95 | + context = super(UpdateFile, self).form_invalid(form) | |
96 | + context.status_code = 400 | |
97 | + | |
98 | + return context | |
99 | + | |
100 | + def get_object(self, queryset=None): | |
101 | + return get_object_or_404(TopicFile, slug = self.kwargs.get('slug')) | |
102 | + | |
103 | + def get_success_url(self): | |
104 | + self.success_url = reverse_lazy('course:file:render_file', args = (self.object.id, )) | |
105 | + | |
106 | + return self.success_url | |
107 | + | |
108 | + | |
109 | +class DeleteFile(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): | |
110 | + allowed_roles = ['professor', 'system_admin'] | |
111 | + login_url = reverse_lazy("core:home") | |
112 | + redirect_field_name = 'next' | |
113 | + model = TopicFile | |
114 | + template_name = 'files/delete_file.html' | |
115 | + | |
116 | + def dispatch(self, *args, **kwargs): | |
117 | + file = get_object_or_404(TopicFile, slug = self.kwargs.get('slug')) | |
118 | + if(not (file.topic.owner == self.request.user)): | |
119 | + return self.handle_no_permission() | |
120 | + return super(DeleteFile, self).dispatch(*args, **kwargs) | |
121 | + | |
122 | + def get_context_data(self, **kwargs): | |
123 | + context = super(DeleteFile, self).get_context_data(**kwargs) | |
124 | + context['course'] = self.object.topic.subject.course | |
125 | + context['subject'] = self.object.topic.subject | |
126 | + context['file'] = self.object | |
127 | + context["topic"] = self.object.topic | |
128 | + return context | |
129 | + | |
130 | + def get_success_url(self): | |
131 | + return reverse_lazy('course:view_topic', kwargs={'slug' : self.object.topic.slug}) | |
4 | 132 | \ No newline at end of file | ... | ... |
forum/migrations/0001_initial.py
1 | 1 | # -*- coding: utf-8 -*- |
2 | -# Generated by Django 1.10 on 2016-10-05 13:38 | |
2 | +# Generated by Django 1.10 on 2016-10-18 20:26 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | -from django.conf import settings | |
6 | 5 | from django.db import migrations, models |
7 | 6 | import django.db.models.deletion |
8 | 7 | |
... | ... | @@ -13,7 +12,6 @@ class Migration(migrations.Migration): |
13 | 12 | |
14 | 13 | dependencies = [ |
15 | 14 | ('courses', '0001_initial'), |
16 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
17 | 15 | ] |
18 | 16 | |
19 | 17 | operations = [ |
... | ... | @@ -38,8 +36,6 @@ class Migration(migrations.Migration): |
38 | 36 | ('message', models.TextField(verbose_name='Post message')), |
39 | 37 | ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')), |
40 | 38 | ('post_date', models.DateTimeField(auto_now_add=True, verbose_name='Post Date')), |
41 | - ('forum', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Forum', verbose_name='Forum')), | |
42 | - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor')), | |
43 | 39 | ], |
44 | 40 | options={ |
45 | 41 | 'verbose_name': 'Post', |
... | ... | @@ -54,7 +50,6 @@ class Migration(migrations.Migration): |
54 | 50 | ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')), |
55 | 51 | ('answer_date', models.DateTimeField(auto_now_add=True, verbose_name='Answer Date')), |
56 | 52 | ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Post', verbose_name='Post')), |
57 | - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor')), | |
58 | 53 | ], |
59 | 54 | options={ |
60 | 55 | 'verbose_name': 'Post Answer', | ... | ... |
... | ... | @@ -0,0 +1,35 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Generated by Django 1.10 on 2016-10-18 20:26 | |
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/tests/test_model_answer.py
... | ... | @@ -93,16 +93,26 @@ class PostAnswerTestCase (TestCase): |
93 | 93 | ) |
94 | 94 | self.post_student.save() |
95 | 95 | |
96 | - self.answer = PostAnswer.objects.create( | |
96 | + self.answerStudent = PostAnswer.objects.create( | |
97 | 97 | user = self.user_student, |
98 | 98 | post = self.post_professor, |
99 | 99 | message = 'testing a post answer', |
100 | 100 | modification_date = '2016-10-05', |
101 | 101 | answer_date = '2016-10-04', |
102 | 102 | ) |
103 | - self.answer.save() | |
103 | + self.answerStudent.save() | |
104 | + | |
105 | + self.answerProfessor = PostAnswer.objects.create( | |
106 | + user = self.user_professor, | |
107 | + post = self.post_student, | |
108 | + message = 'testing a post answer', | |
109 | + modification_date = '2016-10-05', | |
110 | + answer_date = '2016-10-04', | |
111 | + ) | |
112 | + self.answerProfessor.save() | |
104 | 113 | |
105 | 114 | def test_create_answer_post (self): |
115 | + list_answers = PostAnswer.objects.filter(user=self.user_professor).count() | |
106 | 116 | answer = PostAnswer.objects.create( |
107 | 117 | user = self.user_professor, |
108 | 118 | post = self.post_student, |
... | ... | @@ -112,19 +122,46 @@ class PostAnswerTestCase (TestCase): |
112 | 122 | ) |
113 | 123 | answer.save() |
114 | 124 | |
115 | - self.assertEquals (answer, PostAnswer.objects.get(user=self.user_professor, post=self.post_student)) | |
125 | + self.assertEquals (list_answers+1, PostAnswer.objects.filter(user=self.user_professor, post=self.post_student).count()) | |
126 | + | |
127 | + list_answers = PostAnswer.objects.filter(user=self.user_student).count() | |
128 | + answer = PostAnswer.objects.create( | |
129 | + user = self.user_student, | |
130 | + post = self.post_professor, | |
131 | + message = 'testing a post answer2', | |
132 | + modification_date = '2016-10-05', | |
133 | + answer_date = '2016-10-04', | |
134 | + ) | |
135 | + answer.save() | |
136 | + | |
137 | + self.assertEquals (list_answers+1, PostAnswer.objects.filter(user=self.user_student, post=self.post_professor).count()) | |
116 | 138 | |
117 | 139 | def test_update_answer_post (self): |
118 | - self.answer.message = 'updating a answer post' | |
119 | - self.answer.save() | |
140 | + self.answerStudent.message = 'updating a student answer post' | |
141 | + self.answerStudent.save() | |
142 | + answer = PostAnswer.objects.get(message='updating a student answer post') | |
120 | 143 | |
121 | - self.assertEquals(self.answer, PostAnswer.objects.all()[0]) | |
144 | + self.assertEquals(self.answerStudent, answer) | |
122 | 145 | |
123 | - def test_delete_answer_post (self): | |
124 | - answer = PostAnswer.objects.get(user=self.user_student, post=self.post_professor) | |
125 | - self.answer.delete() | |
126 | 146 | |
127 | - try: | |
128 | - answer = PostAnswer.objects.get(user=self.user_student, post=self.post_professor) | |
129 | - except: | |
130 | - pass | |
131 | 147 | \ No newline at end of file |
148 | + self.answerProfessor.message = 'updating a professor answer post' | |
149 | + self.answerProfessor.save() | |
150 | + answer = PostAnswer.objects.get(message='updating a professor answer post') | |
151 | + | |
152 | + self.assertEquals(self.answerProfessor, answer) | |
153 | + | |
154 | + def test_delete_answer_post (self): | |
155 | + list_studentAnswers = PostAnswer.objects.filter(user=self.user_student).count() | |
156 | + self.assertEquals(list_studentAnswers, 1) | |
157 | + | |
158 | + self.answerStudent.delete() | |
159 | + list_studentAnswers = PostAnswer.objects.filter(user=self.user_student).count() | |
160 | + self.assertEquals(list_studentAnswers, 0) | |
161 | + | |
162 | + list_professorAnswers = PostAnswer.objects.filter(user=self.user_professor).count() | |
163 | + self.assertEquals(list_professorAnswers, 1) | |
164 | + | |
165 | + self.answerProfessor.delete() | |
166 | + list_professorAnswers = PostAnswer.objects.filter(user=self.user_professor).count() | |
167 | + self.assertEquals(list_professorAnswers, 0) | |
168 | + | |
132 | 169 | \ No newline at end of file | ... | ... |
forum/tests/test_model_forum.py
... | ... | @@ -77,7 +77,9 @@ class ForumTestCase (TestCase): |
77 | 77 | self.forum.save() |
78 | 78 | |
79 | 79 | def test_create_forum (self): |
80 | - forum = Forum.objects.create( | |
80 | + list_forum = Forum.objects.all().count() | |
81 | + | |
82 | + forum = Forum.objects.create( | |
81 | 83 | topic=self.topic, |
82 | 84 | name = 'forum test2', |
83 | 85 | description = 'description of the forum test', |
... | ... | @@ -85,22 +87,20 @@ class ForumTestCase (TestCase): |
85 | 87 | modification_date = '2016-10-03', |
86 | 88 | limit_date = '2017-10-05', |
87 | 89 | ) |
88 | - forum.save() | |
90 | + forum.save() | |
89 | 91 | |
90 | - self.assertEquals(forum, Forum.objects.filter(name='forum test2')[0]) | |
92 | + self.assertEquals(list_forum+1, Forum.objects.all().count()) | |
91 | 93 | |
92 | - def test_update_forum(self): | |
94 | + def test_update_forum(self): | |
95 | + list_forum = Forum.objects.all().count() | |
93 | 96 | self.forum.name = 'forum test updated' |
94 | 97 | self.forum.save() |
95 | 98 | |
96 | 99 | self.assertEquals(self.forum, Forum.objects.get(name='forum test updated')) |
100 | + self.assertEquals(list_forum, Forum.objects.all().count()) | |
97 | 101 | |
98 | 102 | def test_delete_forum (self): |
99 | - forum = Forum.objects.get(name='forum test') | |
103 | + list_forum = Forum.objects.all().count() | |
100 | 104 | self.forum.delete() |
101 | 105 | |
102 | - try: | |
103 | - forum = Forum.objects.get(name='forum test') | |
104 | - except: | |
105 | - pass | |
106 | - | |
107 | 106 | \ No newline at end of file |
107 | + self.assertEquals(list_forum-1, Forum.objects.all().count()) | |
108 | 108 | \ No newline at end of file | ... | ... |
forum/tests/test_model_post.py
... | ... | @@ -94,6 +94,8 @@ class PostTestCase (TestCase): |
94 | 94 | self.post_student.save() |
95 | 95 | |
96 | 96 | def test_create_post_professor (self): |
97 | + list_post = Post.objects.all().count() | |
98 | + | |
97 | 99 | post_professor = Post.objects.create( |
98 | 100 | user = self.user_professor, |
99 | 101 | message = 'posting', |
... | ... | @@ -103,9 +105,11 @@ class PostTestCase (TestCase): |
103 | 105 | ) |
104 | 106 | post_professor.save() |
105 | 107 | |
106 | - self.assertEquals (post_professor, Post.objects.get(user=self.user_professor, message='posting')) | |
108 | + self.assertEquals(list_post+1, Post.objects.all().count()) | |
107 | 109 | |
108 | 110 | def test_create_post_student (self): |
111 | + list_post = Post.objects.all().count() | |
112 | + | |
109 | 113 | post_student = Post.objects.create( |
110 | 114 | user = self.user_student, |
111 | 115 | message = 'posting', |
... | ... | @@ -115,34 +119,35 @@ class PostTestCase (TestCase): |
115 | 119 | ) |
116 | 120 | post_student.save() |
117 | 121 | |
118 | - self.assertEquals (post_student, Post.objects.get(user=self.user_student, message='posting')) | |
122 | + self.assertEquals(list_post+1, Post.objects.all().count()) | |
119 | 123 | |
120 | 124 | def test_update_post_professor (self): |
125 | + list_post = Post.objects.all().count() | |
121 | 126 | self.post_professor.message = 'updating a post as professor' |
122 | 127 | self.post_professor.save() |
123 | 128 | |
124 | - self.assertEquals(self.post_professor, Post.objects.all()[1]) | |
129 | + self.assertEquals(self.post_professor, Post.objects.get(message='updating a post as professor')) | |
130 | + self.assertEquals(list_post, Post.objects.all().count()) | |
125 | 131 | |
126 | 132 | def test_update_post_student (self): |
133 | + list_post = Post.objects.all().count() | |
127 | 134 | self.post_student.message = 'updating a post as student' |
128 | 135 | self.post_student.save() |
129 | 136 | |
130 | - self.assertEquals(self.post_student, Post.objects.all()[1]) | |
137 | + self.assertEquals(self.post_student, Post.objects.get(message='updating a post as student')) | |
138 | + self.assertEquals(list_post, Post.objects.all().count()) | |
131 | 139 | |
132 | 140 | def test_delete_post_professor (self): |
141 | + list_post = Post.objects.all().count() | |
142 | + | |
133 | 143 | post = Post.objects.get(user=self.user_professor, message='posting a test on forum as professor') |
134 | 144 | self.post_professor.delete() |
135 | 145 | |
136 | - try: | |
137 | - post = Post.objects.get(user=self.user_professor, message='posting a test on forum as professor') | |
138 | - except: | |
139 | - pass | |
146 | + self.assertEquals(list_post-1, Post.objects.all().count()) | |
140 | 147 | |
141 | 148 | def test_delete_post_student (self): |
149 | + list_post = Post.objects.all().count() | |
142 | 150 | post = Post.objects.get(user=self.user_student, message='posting a test on forum as student') |
143 | 151 | self.post_student.delete() |
144 | 152 | |
145 | - try: | |
146 | - post = Post.objects.get(user=self.user_student, message='posting a test on forum as student') | |
147 | - except: | |
148 | - pass | |
149 | 153 | \ No newline at end of file |
154 | + self.assertEquals(list_post-1, Post.objects.all().count()) | |
150 | 155 | \ No newline at end of file | ... | ... |
forum/tests/test_view_forum.py
... | ... | @@ -10,7 +10,6 @@ from forum.models import Forum, Post, PostAnswer |
10 | 10 | class ForumViewTestCase (TestCase): |
11 | 11 | |
12 | 12 | def setUp(self): |
13 | - self.client = Client() | |
14 | 13 | |
15 | 14 | self.user = User.objects.create_user( |
16 | 15 | username = 'test', |
... | ... | @@ -21,6 +20,26 @@ class ForumViewTestCase (TestCase): |
21 | 20 | ) |
22 | 21 | assign_role(self.user, 'system_admin') |
23 | 22 | |
23 | + self.user_professor = User.objects.create_user( | |
24 | + username = 'professor', | |
25 | + email = 'professor@amadeus.com', | |
26 | + is_staff = False, | |
27 | + is_active = True, | |
28 | + password = 'testing', | |
29 | + type_profile = 1 | |
30 | + ) | |
31 | + assign_role(self.user_professor, 'professor') | |
32 | + | |
33 | + self.user_student = User.objects.create_user( | |
34 | + username = 'student', | |
35 | + email = 'student@amadeus.com', | |
36 | + is_staff = False, | |
37 | + is_active = True, | |
38 | + password = 'testing', | |
39 | + type_profile = 2 | |
40 | + ) | |
41 | + assign_role(self.user_student, 'student') | |
42 | + | |
24 | 43 | self.category = CourseCategory.objects.create( |
25 | 44 | name = 'Category test', |
26 | 45 | slug = 'category_test' |
... | ... | @@ -87,11 +106,15 @@ class ForumViewTestCase (TestCase): |
87 | 106 | ) |
88 | 107 | self.answer.save() |
89 | 108 | |
90 | - | |
109 | + self.client = Client() | |
91 | 110 | self.client.login(username='test', password='testing') |
92 | - self.index_url = reverse('course:forum:view', kwargs={'slug':self.forum.slug}) | |
93 | - self.create_url = reverse('course:forum:create') | |
94 | - self.update_url = reverse('course:forum:update', kwargs={'pk':self.forum.pk}) | |
111 | + | |
112 | + self.client_professor = Client() | |
113 | + self.client_professor.login (username='professor', password='testing') | |
114 | + | |
115 | + self.client_student = Client() | |
116 | + self.client_student.login (username='student', password='testing') | |
117 | + | |
95 | 118 | |
96 | 119 | self.createPost_url = reverse('course:forum:create_post') |
97 | 120 | self.updatePost_url = reverse('course:forum:update_post', kwargs={'pk':self.post.pk}) |
... | ... | @@ -99,61 +122,137 @@ class ForumViewTestCase (TestCase): |
99 | 122 | ######################### ForumDetailView ######################### |
100 | 123 | |
101 | 124 | def test_ForumDetail_view_ok (self): |
102 | - response = self.client.get(self.index_url) | |
125 | + url = reverse('course:forum:view', kwargs={'slug':self.forum.slug}) | |
126 | + | |
127 | + response = self.client.get(url) | |
128 | + self.assertEquals(response.status_code, 200) | |
129 | + | |
130 | + response = self.client_professor.get(url) | |
131 | + self.assertEquals(response.status_code, 200) | |
132 | + | |
133 | + response = self.client_student.get(url) | |
103 | 134 | self.assertEquals(response.status_code, 200) |
104 | - self.assertTemplateUsed(response, 'forum/forum_view.html') | |
105 | 135 | |
106 | 136 | def test_ForumDetail_context(self): |
107 | - response = self.client.get(self.index_url) | |
137 | + url = reverse('course:forum:view', kwargs={'slug':self.forum.slug}) | |
138 | + | |
139 | + response = self.client.get(url) | |
108 | 140 | self.assertTrue('forum' in response.context) |
109 | 141 | |
142 | + response = self.client_professor.get(url) | |
143 | + self.assertTrue('forum' in response.context) | |
144 | + | |
145 | + response = self.client_student.get(url) | |
146 | + self.assertTrue('forum' in response.context) | |
147 | + | |
148 | + | |
110 | 149 | ######################### CreateForumView ######################### |
111 | 150 | |
112 | 151 | def test_CreateForum_view_ok (self): |
113 | - response = self.client.get(self.create_url) | |
152 | + url = reverse('course:forum:create') | |
153 | + | |
154 | + response = self.client.get(url) | |
155 | + self.assertEquals(response.status_code, 200) | |
156 | + | |
157 | + response = self.client_professor.get(url) | |
158 | + self.assertEquals(response.status_code, 200) | |
159 | + | |
160 | + response = self.client_student.get(url) | |
114 | 161 | self.assertEquals(response.status_code, 200) |
115 | - self.assertTemplateUsed(response, 'forum/forum_form.html') | |
116 | 162 | |
117 | - def test_CreateForum_context(self): | |
118 | - response = self.client.get(self.create_url) | |
163 | + def test_CreateForum_context(self): | |
164 | + url = reverse('course:forum:create') | |
165 | + | |
166 | + response = self.client.get(url) | |
167 | + self.assertTrue('form' in response.context) | |
168 | + | |
169 | + response = self.client_professor.get(url) | |
170 | + self.assertTrue('form' in response.context) | |
171 | + | |
172 | + response = self.client_student.get(url) | |
119 | 173 | self.assertTrue('form' in response.context) |
120 | 174 | |
121 | 175 | def test_CreateForum_form_error (self): |
176 | + url = reverse('course:forum:create') | |
122 | 177 | data = {'name':'', 'limit_date': '', 'description':'', 'topic':''} |
123 | - response = self.client.post(self.create_url, data) | |
178 | + list_forum = Forum.objects.all().count() | |
179 | + | |
180 | + response = self.client.post(url, data) | |
181 | + self.assertEquals (response.status_code, 400) | |
182 | + self.assertEquals(list_forum, Forum.objects.all().count()) | |
183 | + | |
184 | + response = self.client_professor.post(url, data) | |
124 | 185 | self.assertEquals (response.status_code, 400) |
186 | + self.assertEquals(list_forum, Forum.objects.all().count()) | |
187 | + | |
188 | + response = self.client_student.post(url, data) | |
189 | + self.assertEquals (response.status_code, 400) | |
190 | + self.assertEquals(list_forum, Forum.objects.all().count()) | |
125 | 191 | |
126 | 192 | def test_CreateForum_form_ok (self): |
193 | + url = reverse('course:forum:create') | |
127 | 194 | data = { |
128 | 195 | 'name':'Forum Test2', |
129 | 196 | 'limit_date': '2017-10-05', |
130 | 197 | 'description':'Test', |
131 | 198 | 'topic':str(self.topic.id) |
132 | 199 | } |
200 | + list_forum = Forum.objects.all().count() | |
201 | + | |
202 | + response = self.client.post(url, data) | |
203 | + self.assertEquals (response.status_code, 302) | |
204 | + self.assertEquals(list_forum+1, Forum.objects.all().count()) | |
133 | 205 | |
134 | - response = self.client.post(self.create_url, data) | |
206 | + response = self.client_professor.post(url, data) | |
135 | 207 | self.assertEquals (response.status_code, 302) |
208 | + self.assertEquals(list_forum+2, Forum.objects.all().count()) | |
136 | 209 | |
137 | - forum = Forum.objects.get(name='Forum Test2') | |
210 | + response = self.client_student.post(url, data) | |
211 | + self.assertEquals (response.status_code, 302) | |
212 | + self.assertEquals(list_forum+3, Forum.objects.all().count()) | |
138 | 213 | |
139 | 214 | ######################### UpdateForumView ######################### |
140 | 215 | |
141 | 216 | def test_UpdateForum_view_ok (self): |
142 | - response = self.client.get(self.update_url) | |
217 | + url = reverse('course:forum:update', kwargs={'pk':self.forum.pk}) | |
218 | + | |
219 | + response = self.client.get(url) | |
220 | + self.assertEquals(response.status_code, 200) | |
221 | + | |
222 | + response = self.client_professor.get(url) | |
143 | 223 | self.assertEquals(response.status_code, 200) |
144 | - self.assertTemplateUsed(response, 'forum/forum_form.html') | |
145 | 224 | |
146 | - def test_UpdateForum_context(self): | |
147 | - response = self.client.get(self.update_url) | |
225 | + response = self.client_student.get(url) | |
226 | + self.assertEquals(response.status_code, 200) | |
227 | + | |
228 | + | |
229 | + def test_UpdateForum_context(self): | |
230 | + url = reverse('course:forum:update', kwargs={'pk':self.forum.pk}) | |
231 | + | |
232 | + response = self.client.get(url) | |
233 | + self.assertTrue('form' in response.context) | |
234 | + | |
235 | + response = self.client_professor.get(url) | |
236 | + self.assertTrue('form' in response.context) | |
237 | + | |
238 | + response = self.client_student.get(url) | |
148 | 239 | self.assertTrue('form' in response.context) |
149 | 240 | |
150 | 241 | def test_UpdateForum_form_error (self): |
242 | + url = reverse('course:forum:update', kwargs={'pk':self.forum.pk}) | |
151 | 243 | data = {'name':'', 'limit_date': '', 'description':''} |
152 | 244 | |
153 | - response = self.client.post(self.update_url, data) | |
245 | + response = self.client.post(url, data) | |
246 | + self.assertEquals (response.status_code, 400) | |
247 | + | |
248 | + response = self.client_professor.post(url, data) | |
249 | + self.assertEquals (response.status_code, 400) | |
250 | + | |
251 | + response = self.client_student.post(url, data) | |
154 | 252 | self.assertEquals (response.status_code, 400) |
155 | 253 | |
156 | 254 | def test_UpdateForum_form_ok (self): |
255 | + url = reverse('course:forum:update', kwargs={'pk':self.forum.pk}) | |
157 | 256 | data = { |
158 | 257 | 'name':'Forum Updated', |
159 | 258 | 'limit_date': '2017-10-05', |
... | ... | @@ -161,11 +260,26 @@ class ForumViewTestCase (TestCase): |
161 | 260 | 'topic':str(self.topic.id) |
162 | 261 | } |
163 | 262 | |
164 | - response = self.client.post(self.update_url, data) | |
263 | + self.assertEquals(Forum.objects.all()[0].name, 'forum test') | |
264 | + response = self.client.post(url, data) | |
165 | 265 | self.assertEquals (response.status_code, 302) |
166 | - | |
266 | + self.assertEquals(Forum.objects.all()[0].name, 'Forum Updated') | |
167 | 267 | forum = Forum.objects.get(name='Forum Updated') |
168 | 268 | |
269 | + data['name'] = 'Forum Updated as professor' | |
270 | + self.assertEquals(Forum.objects.all()[0].name, 'Forum Updated') | |
271 | + response = self.client_professor.post(url, data) | |
272 | + self.assertEquals (response.status_code, 302) | |
273 | + self.assertEquals(Forum.objects.all()[0].name, 'Forum Updated as professor') | |
274 | + forum = Forum.objects.get(name='Forum Updated as professor') | |
275 | + | |
276 | + data['name'] = 'Forum Updated as student' | |
277 | + self.assertEquals(Forum.objects.all()[0].name, 'Forum Updated as professor') | |
278 | + response = self.client_student.post(url, data) | |
279 | + self.assertEquals (response.status_code, 302) | |
280 | + self.assertEquals(Forum.objects.all()[0].name, 'Forum Updated as student') | |
281 | + forum = Forum.objects.get(name='Forum Updated as student') | |
282 | + | |
169 | 283 | ######################### CreatePostView ######################### |
170 | 284 | |
171 | 285 | def test_CreatePost_form_error (self): | ... | ... |
links/admin.py
... | ... | @@ -3,8 +3,8 @@ from django.contrib import admin |
3 | 3 | from .models import Link |
4 | 4 | |
5 | 5 | class LinkAdmin(admin.ModelAdmin): |
6 | - list_display = ['name', 'link','description'] | |
7 | - search_fields = ['name', 'link','description'] | |
6 | + list_display = ['name', 'link_url','link_description'] | |
7 | + search_fields = ['name', 'link_url','link_description'] | |
8 | 8 | |
9 | 9 | |
10 | 10 | admin.site.register(Link, LinkAdmin) | ... | ... |
links/forms.py
... | ... | @@ -5,16 +5,16 @@ import validators |
5 | 5 | class CreateLinkForm(forms.ModelForm): |
6 | 6 | |
7 | 7 | def clean_link(self): |
8 | - link = self.cleaned_data['link'] | |
9 | - if not validators.url(link): | |
8 | + link_url = self.cleaned_data['link_url'] | |
9 | + if not validators.url(link_url): | |
10 | 10 | raise forms.ValidationError(_('Please enter a valid URL')) |
11 | - return link | |
11 | + return link_url | |
12 | 12 | |
13 | 13 | class Meta: |
14 | 14 | model = Link |
15 | - fields = ['name','link','description'] | |
15 | + fields = ['name','link_url','link_description'] | |
16 | 16 | |
17 | 17 | class UpdateLinkForm(forms.ModelForm): |
18 | 18 | class Meta: |
19 | 19 | model = Link |
20 | - fields = ['name','link','description'] | |
20 | + fields = ['name','link_url','link_description'] | ... | ... |
links/migrations/0001_initial.py
1 | 1 | # -*- coding: utf-8 -*- |
2 | -# Generated by Django 1.10 on 2016-10-06 17:57 | |
2 | +# Generated by Django 1.10 on 2016-10-18 20:26 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | 5 | from django.db import migrations, models |
6 | +import django.db.models.deletion | |
6 | 7 | |
7 | 8 | |
8 | 9 | class Migration(migrations.Migration): |
... | ... | @@ -10,20 +11,21 @@ class Migration(migrations.Migration): |
10 | 11 | initial = True |
11 | 12 | |
12 | 13 | dependencies = [ |
14 | + ('courses', '0001_initial'), | |
13 | 15 | ] |
14 | 16 | |
15 | 17 | operations = [ |
16 | 18 | migrations.CreateModel( |
17 | 19 | name='Link', |
18 | 20 | fields=[ |
19 | - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
20 | - ('name', models.CharField(max_length=100)), | |
21 | - ('link', models.URLField()), | |
22 | - ('description', models.CharField(max_length=200)), | |
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)), | |
23 | 24 | ], |
24 | 25 | options={ |
25 | - 'verbose_name_plural': 'Links', | |
26 | 26 | 'verbose_name': 'Link', |
27 | + 'verbose_name_plural': 'Links', | |
27 | 28 | }, |
29 | + bases=('courses.material',), | |
28 | 30 | ), |
29 | 31 | ] | ... | ... |
links/models.py
1 | - | |
2 | 1 | from django.db import models |
3 | 2 | from courses.models import Material |
4 | 3 | from autoslug.fields import AutoSlugField |
5 | 4 | # Create your models here. |
6 | -class Link(models.Model): | |
7 | - name = models.CharField(max_length=100) | |
8 | - link = models.URLField() | |
9 | - description = models.CharField(max_length=200) | |
5 | +class Link(Material): | |
6 | + link_url = models.URLField() | |
7 | + link_description = models.CharField(max_length=200) | |
10 | 8 | class Meta: |
11 | 9 | verbose_name = 'Link' |
12 | 10 | verbose_name_plural = "Links" | ... | ... |
links/urls.py
... | ... | @@ -2,5 +2,7 @@ from django.conf.urls import url, include |
2 | 2 | from . import views |
3 | 3 | |
4 | 4 | urlpatterns = [ |
5 | - url(r'^$', views.CreateLink.as_view(), name='teste') | |
5 | + url(r'^$', views.CreateLink.as_view(), name='create_link'), | |
6 | + url(r'^deletelink/(?P<linkname>[\w_-]+)/$', views.deleteLink,name = 'delete_link'), | |
7 | + url(r'^updatelink/(?P<linkname>[\w_-]+)/$', views.UpdateLink.as_view(),name = 'update_link'), | |
6 | 8 | ] | ... | ... |
links/views.py
... | ... | @@ -13,7 +13,7 @@ class CreateLink(generic.CreateView): |
13 | 13 | template_name = 'links/create_link.html' |
14 | 14 | form_class = CreateLinkForm |
15 | 15 | success_url = reverse_lazy('course:manage') |
16 | - context_object_name = 'links' | |
16 | + context_object_name = 'form' | |
17 | 17 | |
18 | 18 | def form_valid(self, form): |
19 | 19 | form.save() |
... | ... | @@ -26,7 +26,6 @@ class CreateLink(generic.CreateView): |
26 | 26 | context['form'] = CreateLinkForm |
27 | 27 | return context |
28 | 28 | |
29 | - | |
30 | 29 | def deleteLink(request,linkname): |
31 | 30 | link = get_object_or_404(Link,name = linkname) |
32 | 31 | link.delete() | ... | ... |
poll/migrations/0001_initial.py
1 | 1 | # -*- coding: utf-8 -*- |
2 | -# Generated by Django 1.10 on 2016-10-05 13:38 | |
2 | +# Generated by Django 1.10 on 2016-10-18 20:26 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | 5 | from django.db import migrations, models |
... | ... | @@ -29,19 +29,32 @@ class Migration(migrations.Migration): |
29 | 29 | }, |
30 | 30 | ), |
31 | 31 | migrations.CreateModel( |
32 | + name='AnswersStudent', | |
33 | + fields=[ | |
34 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
35 | + ('status', models.BooleanField(default=False, verbose_name='Answered')), | |
36 | + ('answered_in', models.DateTimeField(auto_now=True, verbose_name='Answered Date')), | |
37 | + ('answer', models.ManyToManyField(related_name='answers_stundet', to='poll.Answer', verbose_name='Answers Students')), | |
38 | + ], | |
39 | + options={ | |
40 | + 'verbose_name': 'Answer Stundent', | |
41 | + 'verbose_name_plural': 'Answers Student', | |
42 | + }, | |
43 | + ), | |
44 | + migrations.CreateModel( | |
32 | 45 | name='Poll', |
33 | 46 | fields=[ |
34 | 47 | ('activity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Activity')), |
35 | 48 | ], |
36 | 49 | options={ |
37 | - 'verbose_name_plural': 'Polls', | |
38 | 50 | 'verbose_name': 'Poll', |
51 | + 'verbose_name_plural': 'Polls', | |
39 | 52 | }, |
40 | 53 | bases=('courses.activity',), |
41 | 54 | ), |
42 | 55 | migrations.AddField( |
43 | - model_name='answer', | |
56 | + model_name='answersstudent', | |
44 | 57 | name='poll', |
45 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='poll.Poll', verbose_name='Answers'), | |
58 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundet', to='poll.Poll', verbose_name='Poll'), | |
46 | 59 | ), |
47 | 60 | ] | ... | ... |
poll/migrations/0002_answersstudent.py
... | ... | @@ -1,33 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-12 18:26 | |
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 | - dependencies = [ | |
13 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
14 | - ('poll', '0001_initial'), | |
15 | - ] | |
16 | - | |
17 | - operations = [ | |
18 | - migrations.CreateModel( | |
19 | - name='AnswersStudent', | |
20 | - fields=[ | |
21 | - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
22 | - ('status', models.BooleanField(default=False, verbose_name='Answered')), | |
23 | - ('answered_in', models.DateTimeField(auto_now=True, verbose_name='Answered Date')), | |
24 | - ('answer', models.ManyToManyField(related_name='answers_stundet', to='poll.Answer', verbose_name='Answers Students')), | |
25 | - ('poll', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundet', to='poll.Poll', verbose_name='Answers')), | |
26 | - ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundent', to=settings.AUTH_USER_MODEL, verbose_name='Student')), | |
27 | - ], | |
28 | - options={ | |
29 | - 'verbose_name': 'Answer Stundent', | |
30 | - 'verbose_name_plural': 'Answers Student', | |
31 | - }, | |
32 | - ), | |
33 | - ] |
... | ... | @@ -0,0 +1,30 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Generated by Django 1.10 on 2016-10-18 20:26 | |
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/0003_auto_20161012_1638.py
... | ... | @@ -1,21 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-12 19:38 | |
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 | - ('poll', '0002_answersstudent'), | |
13 | - ] | |
14 | - | |
15 | - operations = [ | |
16 | - migrations.AlterField( | |
17 | - model_name='answersstudent', | |
18 | - name='poll', | |
19 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundet', to='poll.Poll', verbose_name='Poll'), | |
20 | - ), | |
21 | - ] |
poll/static/js/modal_poll.js
poll/static/js/modals_requisitions.js
1 | -function get(url, id_modal, id_div_modal){ | |
2 | - $.get(url, function(data){ | |
3 | - if($(id_modal).length){ | |
4 | - $(id_div_modal).empty(); | |
5 | - $(id_div_modal).append(data); | |
6 | - } else { | |
7 | - $(id_div_modal).append(data); | |
8 | - } | |
9 | - $(id_modal).modal('show'); | |
10 | - }); | |
11 | -} | |
12 | - | |
13 | -// function remove(url, id_li_link){ | |
14 | -// $.post(url, function(data){ | |
15 | -// $(id_li_link).remove(); | |
16 | -// }).fail(function(data){ | |
17 | -// alert("Error ao excluir a enquete"); | |
18 | -// alert(data); | |
19 | -// }); | |
20 | -// } | |
1 | +var modal = { | |
2 | + get: function (url, id_modal, id_div_modal){ | |
3 | + $.get(url, function(data){ | |
4 | + if($(id_modal).length){ | |
5 | + $(id_div_modal).empty(); | |
6 | + $(id_div_modal).append(data); | |
7 | + } else { | |
8 | + $(id_div_modal).append(data); | |
9 | + } | |
10 | + $(id_modal).modal('show'); | |
11 | + }); | |
12 | + } | |
13 | +}; | ... | ... |
poll/static/sample.txt
poll/templates/poll/view.html
... | ... | @@ -30,6 +30,6 @@ |
30 | 30 | {% block button_save %} |
31 | 31 | <!-- Put curtom buttons here!!! --> |
32 | 32 | {% if not status %} |
33 | -<button type="button" onclick="javascript:get('{% url 'course:poll:answer_student_poll' poll.slug%}','#poll','#modal_poll');$('div.modal-backdrop.fade.in').remove();" class="btn btn-primary btn-raised">{% trans "Answer" %}</button> | |
33 | +<button type="button" onclick="javascript:modal.get('{% url 'course:poll:answer_student_poll' poll.slug%}','#poll','#modal_poll');$('div.modal-backdrop.fade.in').remove();" class="btn btn-primary btn-raised">{% trans "Answer" %}</button> | |
34 | 34 | {% endif %} |
35 | 35 | {% endblock button_save %} | ... | ... |
... | ... | @@ -0,0 +1,14 @@ |
1 | +from django import template | |
2 | +from rolepermissions.verifications import has_role | |
3 | + | |
4 | +register = template.Library() | |
5 | + | |
6 | +@register.simple_tag | |
7 | +def professor_subject(subject, user): | |
8 | + if (has_role(user,'system_admin')): | |
9 | + return True | |
10 | + | |
11 | + if (user in subject.professors.all()): | |
12 | + return True | |
13 | + | |
14 | + return False | ... | ... |
poll/tests/poll.py
... | ... | @@ -80,21 +80,23 @@ class PollTestCase(TestCase): |
80 | 80 | self.poll.save() |
81 | 81 | |
82 | 82 | def test_poll_create(self): |
83 | - self.client.login(username='professor', password='testing') | |
84 | - poll = self.topic.activities.all().count() | |
85 | 83 | url = reverse('course:poll:create_poll',kwargs={'slug':self.topic.slug}) |
86 | 84 | data = { |
87 | 85 | "name": 'create poll test', |
88 | 86 | "limit_date":'2016-10-06', |
89 | 87 | "all_students":True, |
90 | 88 | } |
91 | - response = self.client.post(url, data) | |
92 | - self.assertEqual(poll + 1, self.topic.activities.all().count()) # create a new poll | |
89 | + | |
93 | 90 | self.client.login(username='student', password='testing') |
94 | 91 | poll = self.topic.activities.all().count() |
95 | 92 | response = self.client.post(url, data) |
96 | 93 | self.assertEqual(poll, self.topic.activities.all().count()) # don't create a new poll |
97 | 94 | |
95 | + self.client.login(username='professor', password='testing') | |
96 | + poll = self.topic.activities.all().count() | |
97 | + response = self.client.post(url, data) | |
98 | + self.assertEqual(poll + 1, self.topic.activities.all().count()) # create a new poll | |
99 | + | |
98 | 100 | def test_poll_update(self): |
99 | 101 | self.client.login(username='professor', password='testing') |
100 | 102 | url = reverse('course:poll:update_poll',kwargs={'slug':self.poll.slug}) | ... | ... |
poll/views.py
... | ... | @@ -34,7 +34,6 @@ class ViewPoll(LoginRequiredMixin,generic.DetailView): |
34 | 34 | context['subject'] = poll.topic.subject |
35 | 35 | context['subjects'] = poll.topic.subject.course.subjects.all() |
36 | 36 | answered = AnswersStudent.objects.filter(poll = poll, student=self.request.user) |
37 | - print (answered) | |
38 | 37 | if answered.count()<1: |
39 | 38 | context['status'] = False |
40 | 39 | else: |
... | ... | @@ -144,10 +143,8 @@ class UpdatePoll(LoginRequiredMixin,HasRoleMixin,generic.UpdateView): |
144 | 143 | context['course'] = poll.topic.subject.course |
145 | 144 | context['subject'] = poll.topic.subject |
146 | 145 | context['subjects'] = poll.topic.subject.course.subjects.all() |
147 | - | |
148 | 146 | answers = {} |
149 | 147 | for answer in poll.answers.all(): |
150 | - # print (key.answer) | |
151 | 148 | answers[answer.order] = answer.answer |
152 | 149 | |
153 | 150 | keys = sorted(answers) |
... | ... | @@ -213,7 +210,6 @@ class AnswerStudentPoll(LoginRequiredMixin,generic.CreateView): |
213 | 210 | |
214 | 211 | def get_context_data(self, **kwargs): |
215 | 212 | context = super(AnswerStudentPoll, self).get_context_data(**kwargs) |
216 | - print (self.kwargs.get('slug')) | |
217 | 213 | poll = get_object_or_404(Poll, slug = self.kwargs.get('slug')) |
218 | 214 | context['poll'] = poll |
219 | 215 | context['topic'] = poll.topic |
... | ... | @@ -221,7 +217,6 @@ class AnswerStudentPoll(LoginRequiredMixin,generic.CreateView): |
221 | 217 | context['subject'] = poll.topic.subject |
222 | 218 | context['subjects'] = poll.topic.subject.course.subjects.all() |
223 | 219 | |
224 | - print (self.request.method) | |
225 | 220 | answers = {} |
226 | 221 | for answer in poll.answers.all(): |
227 | 222 | answers[answer.order] = answer.answer | ... | ... |
users/admin.py
... | ... | @@ -5,6 +5,5 @@ from .forms import AdminUserForm |
5 | 5 | class UserAdmin(admin.ModelAdmin): |
6 | 6 | list_display = ['username', 'name', 'email', 'is_staff', 'is_active'] |
7 | 7 | search_fields = ['username', 'name', 'email'] |
8 | - # form = AdminUserForm | |
9 | 8 | |
10 | -admin.site.register(User, UserAdmin) | |
11 | 9 | \ No newline at end of file |
10 | +admin.site.register(User, UserAdmin) | ... | ... |