Commit a4c22c10e5b9a202d86ff3a59efac08728605aa7
Exists in
master
and in
5 other branches
fixing conflit
Showing
68 changed files
with
1242 additions
and
752 deletions
Show diff stats
amadeus/roles.py
amadeus/settings.py
... | ... | @@ -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, MymeType | |
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,7 @@ class LogAdmin(admin.ModelAdmin): |
18 | 17 | list_display = ['datetime', 'user', 'action_resource'] |
19 | 18 | search_fields = ['user'] |
20 | 19 | |
21 | -class MymeTypeAdmin(admin.ModelAdmin): | |
20 | +class MimeTypeAdmin(admin.ModelAdmin): | |
22 | 21 | list_display = ['typ', 'icon'] |
23 | 22 | search_fields = ['typ', 'icon'] |
24 | 23 | |
... | ... | @@ -26,4 +25,4 @@ admin.site.register(Action, ActionAdmin) |
26 | 25 | admin.site.register(Resource, ResourceAdmin) |
27 | 26 | admin.site.register(Action_Resource, ActionResourceAdmin) |
28 | 27 | admin.site.register(Log, LogAdmin) |
29 | -admin.site.register(MymeType, MymeTypeAdmin) | |
30 | 28 | \ No newline at end of file |
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-17 15:49 | |
2 | +# Generated by Django 1.10 on 2016-10-18 02:46 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | 5 | import autoslug.fields |
6 | +from django.conf import settings | |
6 | 7 | from django.db import migrations, models |
7 | 8 | import django.db.models.deletion |
8 | 9 | |
... | ... | @@ -12,6 +13,7 @@ class Migration(migrations.Migration): |
12 | 13 | initial = True |
13 | 14 | |
14 | 15 | dependencies = [ |
16 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
15 | 17 | ] |
16 | 18 | |
17 | 19 | operations = [ |
... | ... | @@ -23,18 +25,19 @@ class Migration(migrations.Migration): |
23 | 25 | ('created_date', models.DateField(auto_now_add=True, verbose_name='Created Date')), |
24 | 26 | ], |
25 | 27 | options={ |
26 | - 'verbose_name_plural': 'Actions', | |
27 | 28 | 'verbose_name': 'Action', |
29 | + 'verbose_name_plural': 'Actions', | |
28 | 30 | }, |
29 | 31 | ), |
30 | 32 | migrations.CreateModel( |
31 | 33 | name='Action_Resource', |
32 | 34 | fields=[ |
33 | 35 | ('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')), | |
34 | 37 | ], |
35 | 38 | options={ |
36 | - 'verbose_name_plural': 'Action_Resources', | |
37 | 39 | 'verbose_name': 'Action_Resource', |
40 | + 'verbose_name_plural': 'Action_Resources', | |
38 | 41 | }, |
39 | 42 | ), |
40 | 43 | migrations.CreateModel( |
... | ... | @@ -42,22 +45,24 @@ class Migration(migrations.Migration): |
42 | 45 | fields=[ |
43 | 46 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
44 | 47 | ('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')), | |
45 | 50 | ], |
46 | 51 | options={ |
47 | - 'verbose_name_plural': 'Logs', | |
48 | 52 | 'verbose_name': 'Log', |
53 | + 'verbose_name_plural': 'Logs', | |
49 | 54 | }, |
50 | 55 | ), |
51 | 56 | migrations.CreateModel( |
52 | - name='MymeType', | |
57 | + name='MimeType', | |
53 | 58 | fields=[ |
54 | 59 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
55 | 60 | ('typ', models.CharField(max_length=100, unique=True, verbose_name='Type')), |
56 | 61 | ('icon', models.CharField(max_length=50, unique=True, verbose_name='Icon')), |
57 | 62 | ], |
58 | 63 | options={ |
59 | - 'verbose_name_plural': 'Amadeus Myme Types', | |
60 | - 'verbose_name': 'Amadeus Myme Type', | |
64 | + 'verbose_name': 'Amadeus Mime Type', | |
65 | + 'verbose_name_plural': 'Amadeus Mime Types', | |
61 | 66 | }, |
62 | 67 | ), |
63 | 68 | migrations.CreateModel( |
... | ... | @@ -68,10 +73,12 @@ class Migration(migrations.Migration): |
68 | 73 | ('read', models.BooleanField(default=False, verbose_name='Read')), |
69 | 74 | ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), |
70 | 75 | ('action_resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource')), |
76 | + ('actor', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_Performer', to=settings.AUTH_USER_MODEL, verbose_name='Perfomer')), | |
77 | + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notification_Actor', to=settings.AUTH_USER_MODEL, verbose_name='User')), | |
71 | 78 | ], |
72 | 79 | options={ |
73 | - 'verbose_name_plural': 'Notifications', | |
74 | 80 | 'verbose_name': 'Notification', |
81 | + 'verbose_name_plural': 'Notifications', | |
75 | 82 | }, |
76 | 83 | ), |
77 | 84 | migrations.CreateModel( |
... | ... | @@ -84,8 +91,13 @@ class Migration(migrations.Migration): |
84 | 91 | ('url', models.CharField(default='', max_length=100, verbose_name='URL')), |
85 | 92 | ], |
86 | 93 | options={ |
87 | - 'verbose_name_plural': 'Resources', | |
88 | 94 | 'verbose_name': 'Resource', |
95 | + 'verbose_name_plural': 'Resources', | |
89 | 96 | }, |
90 | 97 | ), |
98 | + migrations.AddField( | |
99 | + model_name='action_resource', | |
100 | + name='resource', | |
101 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Resource', verbose_name='Resource'), | |
102 | + ), | |
91 | 103 | ] | ... | ... |
core/migrations/0002_auto_20161017_1249.py
... | ... | @@ -1,50 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-17 15:49 | |
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/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/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/migrations/0001_initial.py
1 | 1 | # -*- coding: utf-8 -*- |
2 | -# Generated by Django 1.10 on 2016-10-17 15:49 | |
2 | +# Generated by Django 1.10 on 2016-10-18 02:46 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | 5 | import autoslug.fields |
6 | +from django.conf import settings | |
6 | 7 | from django.db import migrations, models |
7 | 8 | import django.db.models.deletion |
8 | 9 | import s3direct.fields |
... | ... | @@ -14,6 +15,7 @@ class Migration(migrations.Migration): |
14 | 15 | |
15 | 16 | dependencies = [ |
16 | 17 | ('core', '0001_initial'), |
18 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
17 | 19 | ] |
18 | 20 | |
19 | 21 | operations = [ |
... | ... | @@ -23,6 +25,7 @@ class Migration(migrations.Migration): |
23 | 25 | ('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')), |
24 | 26 | ('limit_date', models.DateField(verbose_name='Deliver Date')), |
25 | 27 | ('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')), | |
26 | 29 | ], |
27 | 30 | bases=('core.resource',), |
28 | 31 | ), |
... | ... | @@ -32,6 +35,7 @@ class Migration(migrations.Migration): |
32 | 35 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
33 | 36 | ('pdf', s3direct.fields.S3DirectField()), |
34 | 37 | ('name', models.CharField(max_length=100)), |
38 | + ('diet', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='courses.Activity')), | |
35 | 39 | ], |
36 | 40 | options={ |
37 | 41 | 'verbose_name_plural': 'Activitys Files', |
... | ... | @@ -68,8 +72,8 @@ class Migration(migrations.Migration): |
68 | 72 | ('image', models.ImageField(blank=True, upload_to='courses/', verbose_name='Image')), |
69 | 73 | ], |
70 | 74 | options={ |
71 | - 'ordering': ('create_date', 'name'), | |
72 | 75 | 'verbose_name_plural': 'Courses', |
76 | + 'ordering': ('create_date', 'name'), | |
73 | 77 | 'verbose_name': 'Course', |
74 | 78 | }, |
75 | 79 | ), |
... | ... | @@ -108,6 +112,7 @@ class Migration(migrations.Migration): |
108 | 112 | fields=[ |
109 | 113 | ('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')), |
110 | 114 | ('all_students', models.BooleanField(default=False, verbose_name='All Students')), |
115 | + ('students', models.ManyToManyField(related_name='materials', to=settings.AUTH_USER_MODEL, verbose_name='Students')), | |
111 | 116 | ], |
112 | 117 | bases=('core.resource',), |
113 | 118 | ), |
... | ... | @@ -123,10 +128,14 @@ class Migration(migrations.Migration): |
123 | 128 | ('end_date', models.DateField(verbose_name='End of Subject Date')), |
124 | 129 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), |
125 | 130 | ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), |
131 | + ('category', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subject_category', to='courses.CategorySubject', verbose_name='Category')), | |
132 | + ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subjects', to='courses.Course', verbose_name='Course')), | |
133 | + ('professors', models.ManyToManyField(related_name='professors_subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors')), | |
134 | + ('students', models.ManyToManyField(related_name='subject_student', to=settings.AUTH_USER_MODEL, verbose_name='Students')), | |
126 | 135 | ], |
127 | 136 | options={ |
128 | - 'ordering': ('create_date', 'name'), | |
129 | 137 | 'verbose_name_plural': 'Subjects', |
138 | + 'ordering': ('create_date', 'name'), | |
130 | 139 | 'verbose_name': 'Subject', |
131 | 140 | }, |
132 | 141 | ), |
... | ... | @@ -137,6 +146,7 @@ class Migration(migrations.Migration): |
137 | 146 | ('name', models.CharField(max_length=100, verbose_name='Name')), |
138 | 147 | ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')), |
139 | 148 | ('description', models.TextField(blank=True, verbose_name='Description')), |
149 | + ('subjects', models.ManyToManyField(to='courses.Subject')), | |
140 | 150 | ], |
141 | 151 | options={ |
142 | 152 | 'verbose_name_plural': 'subject categories', |
... | ... | @@ -153,11 +163,48 @@ class Migration(migrations.Migration): |
153 | 163 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), |
154 | 164 | ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), |
155 | 165 | ('visible', models.BooleanField(default=False, verbose_name='Visible')), |
166 | + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Owner')), | |
167 | + ('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Subject', verbose_name='Subject')), | |
156 | 168 | ], |
157 | 169 | options={ |
158 | - 'ordering': ('create_date', 'name'), | |
159 | 170 | 'verbose_name_plural': 'Topics', |
171 | + 'ordering': ('create_date', 'name'), | |
160 | 172 | 'verbose_name': 'Topic', |
161 | 173 | }, |
162 | 174 | ), |
175 | + migrations.AddField( | |
176 | + model_name='material', | |
177 | + name='topic', | |
178 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='courses.Topic', verbose_name='Topic'), | |
179 | + ), | |
180 | + migrations.AddField( | |
181 | + model_name='linkmaterial', | |
182 | + name='material', | |
183 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_link', to='courses.Material', verbose_name='Material'), | |
184 | + ), | |
185 | + migrations.AddField( | |
186 | + model_name='filematerial', | |
187 | + name='material', | |
188 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_file', to='courses.Material', verbose_name='Material'), | |
189 | + ), | |
190 | + migrations.AddField( | |
191 | + model_name='course', | |
192 | + name='category', | |
193 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_category', to='courses.CourseCategory', verbose_name='Category'), | |
194 | + ), | |
195 | + migrations.AddField( | |
196 | + model_name='course', | |
197 | + name='professors', | |
198 | + field=models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors'), | |
199 | + ), | |
200 | + migrations.AddField( | |
201 | + model_name='course', | |
202 | + name='students', | |
203 | + field=models.ManyToManyField(related_name='courses_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'), | |
204 | + ), | |
205 | + migrations.AddField( | |
206 | + model_name='activity', | |
207 | + name='topic', | |
208 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='courses.Topic', verbose_name='Topic'), | |
209 | + ), | |
163 | 210 | ] | ... | ... |
courses/migrations/0002_auto_20161017_1249.py
... | ... | @@ -1,105 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-17 15:49 | |
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/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): | ... | ... |
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"> |
... | ... | @@ -282,7 +282,7 @@ |
282 | 282 | {% endif %} |
283 | 283 | |
284 | 284 | {% if user|has_role:'professor' or user|has_role:'system_admin' %} |
285 | - | |
285 | + | |
286 | 286 | <div class="form-group"> |
287 | 287 | <a href="{% url 'course:create_subject' course.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> |
288 | 288 | </div> |
... | ... | @@ -314,4 +314,3 @@ |
314 | 314 | </div> |
315 | 315 | |
316 | 316 | {% endblock %} |
317 | - | ... | ... |
courses/templates/subject/form_view_teacher.html
1 | - {% load static i18n list_topic_foruns permission_tags widget_tweaks %} | |
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> | |
5 | 6 | <script type="text/javascript" src="{% static 'js/material.js' %}"></script> |
7 | + <script type = "text/javascript" src="{% static 'link.js' %}"></script> | |
6 | 8 | {% endblock %} |
7 | 9 | |
8 | 10 | <div class="panel-group accordion ui-accordion ui-widget ui-helper-reset ui-sortable" role="tablist" aria-multiselectable="false"> |
... | ... | @@ -24,7 +26,8 @@ |
24 | 26 | <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
25 | 27 | <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> |
26 | 28 | </button> |
27 | - {% if user|has_role:'system_admin' or topic.owner == user %} | |
29 | + {% professor_subject topic.subject user as dropdown_topic %} | |
30 | + {% if dropdown_topic %} | |
28 | 31 | <ul class="dropdown-menu pull-right" aria-labelledby="moreActions"> |
29 | 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> |
30 | 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> |
... | ... | @@ -52,18 +55,23 @@ |
52 | 55 | <div class="dropdown"> |
53 | 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> |
54 | 57 | <ul class="dropdown-menu" aria-labelledby="dLabel"> |
55 | - <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> | |
56 | - <li><a href="javascript:createMaterial('{% url 'course:upload_material' %}', '{{ topic.id }}')">{% trans 'Create 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> | |
57 | 68 | </ul> |
58 | 69 | </div> |
59 | 70 | </div> |
60 | 71 | <ul> |
61 | - {% for file in files %} | |
62 | - <li><i class="fa fa-book" aria-hidden="true"></i> <a href="{{file.file_url}}">{{file}}</a></li> | |
63 | - {% endfor %} | |
64 | - | |
65 | - <!-- <li><i class="fa fa-link" aria-hidden="true"></i> <a href="#" data-toggle="modal" data-target="#linksModal">Link 1</a></li> | |
66 | - <li><i class="fa fa-file-code-o" aria-hidden="true"></i> <a href="#" data-toggle="modal" data-target="#embedModal">EMBED Material</a></li>--> | |
72 | + {% list_topic_file request topic %} | |
73 | + {% list_topic_link request topic%} | |
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> | |
67 | 75 | </ul> |
68 | 76 | </div> |
69 | 77 | <div class="col-xs-4 col-md-4"> |
... | ... | @@ -106,18 +114,14 @@ |
106 | 114 | <div class="dropdown"> |
107 | 115 | <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> |
108 | 116 | <ul class="dropdown-menu" aria-labelledby="dLabel"> |
109 | - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#createLinksModal">Create a Link</a></li> | |
110 | - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#createFileModal">Create a file</a></li> | |
117 | + <li><a href=" javascript:get_modal_link('{% url 'course:links:create_link' %}', '#createLinksModal','#divModalLink') ">Create a Link</a></li> | |
118 | + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#fileModal">Create a file</a></li> | |
111 | 119 | </ul> |
112 | 120 | </div> |
113 | 121 | </div> |
114 | 122 | <ul> |
115 | - <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> | |
116 | - <li><a href="#">Book 1</a> </li> | |
117 | - <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> | |
118 | - <li><a href="#" data-toggle="modal" data-target="#linksModal">Link 1</a></li> | |
119 | - <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> | |
120 | - <li><a href="#" data-toggle="modal" data-target="#embedModal">EMBED Material</a></li> | |
123 | + {% list_topic_link_edit request topic%} | |
124 | + {% list_topic_file_edit request topic %} | |
121 | 125 | </ul> |
122 | 126 | </div> |
123 | 127 | <div class="col-xs-4 col-md-offset-1 col-md-4"> |
... | ... | @@ -129,6 +133,7 @@ |
129 | 133 | <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> |
130 | 134 | <ul class="dropdown-menu" aria-labelledby="dLabel"> |
131 | 135 | <li>Qualquer coisa</li> |
136 | + <li><i class="material-icons">poll</i> <a href="javascript:modal.get('{% url 'course:poll:create_poll' topic.slug%}','#poll','#modal_poll');">{% trans 'Create Poll' %}</a></li> | |
132 | 137 | </ul> |
133 | 138 | </div> |
134 | 139 | </div> |
... | ... | @@ -171,81 +176,9 @@ |
171 | 176 | </div> |
172 | 177 | </div> |
173 | 178 | <!-- END --> |
174 | - | |
175 | - <div class="modal fade" id="editFileModal" tabindex="-1" role="dialog" aria-labelledby="editFileLabel"> | |
176 | - <div class="modal-dialog" role="document"> | |
177 | - <div class="modal-content"> | |
178 | - <div class="modal-header"> | |
179 | - <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
180 | - <h4 class="modal-title" id="editFileLabel">{% trans 'Add File' %}</h4> | |
181 | - </div> | |
182 | - <div class="modal-body"> | |
183 | - <section> | |
184 | - <div class="material_form"></div> | |
185 | - </section> | |
186 | - </div> | |
187 | - <div class="modal-footer"> | |
188 | - <button type="button" onclick="$('#material_create').submit();" class="btn btn-primary btn-raised">{% trans 'Submit' %}</button> | |
189 | - </div> | |
190 | - </div> | |
191 | - </div> | |
192 | - </div> | |
193 | - | |
194 | -{% if user|has_role:'system_admin' or topic.owner == user%} | |
195 | - {% include "files/create_file.html" %} | |
196 | -{% endif %} | |
197 | - <!-- MODAL REMOVE FILE --> | |
198 | - <div class="modal" id="removeFileModal"> | |
199 | - <div class="modal-dialog"> | |
200 | - <div class="modal-content"> | |
201 | - <div class="modal-header"> | |
202 | - <button type="button" class="close" data-dismiss="modal" aria-hidden="true">X</button> | |
203 | - <h4 class="modal-title"></h4> | |
204 | - </div> | |
205 | - <div class="modal-body"> | |
206 | - <p>Do you really want to delete this file?</p> | |
207 | - </div> | |
208 | - <div class="modal-footer"> | |
209 | - | |
210 | - <a href="#" target="_self"><button type="button" class="btn btn-primary" data-dismiss="modal" aria-hidden="true">Confirm</button></a> | |
211 | - | |
212 | - </div> | |
213 | - </div> | |
214 | - </div> | |
215 | - </div> | |
216 | - <!-- END --> | |
217 | - | |
218 | - <!--MODAL VIEW LINK--> | |
219 | - <div class="modal fade" id="linksModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> | |
220 | - <div class="modal-dialog" role="document"> | |
221 | - <div class="modal-content"> | |
222 | - <div class="modal-header"> | |
223 | - <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | |
224 | - <h4 class="modal-title" id="myModalLabel">Links</h4> | |
225 | - </div> | |
226 | - <div class="modal-body"> | |
227 | - <!-- Card --> | |
228 | - <article class="card animated fadeInLeft"> | |
229 | - <img class="card-img-top img-responsive" src="https://www.python.org/static/opengraph-icon-200x200.png" align="left"> | |
230 | - <div class="card-block"> | |
231 | - <b class="card-title">Python</b><p></p> | |
232 | - <b class="text-muted">Guido van Rossum</b> | |
233 | - <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> | |
234 | - <a href="https://www.python.org/" class="btn btn-primary">Read more</a> | |
235 | - </div> | |
236 | - </article> | |
237 | - <!-- .end Card --> | |
238 | - </div> | |
239 | - </div> | |
240 | - </div> | |
241 | - </div> | |
242 | - <!-- EndModal --> | |
243 | - | |
244 | - {% if user|has_role:'system_admin' or topic.owner == user%} | |
179 | + {% professor_subject topic.subject user as professor_links %} | |
180 | + {% if professor_links%} | |
245 | 181 | {% include "links/create_link.html" %} |
246 | - {% endif %} | |
247 | - | |
248 | - {% if user|has_role:'system_admin' or topic.owner == user%} | |
249 | 182 | {% include "links/delete_link.html" %} |
250 | 183 | {% endif %} |
251 | 184 | |
... | ... | @@ -365,7 +298,8 @@ |
365 | 298 | |
366 | 299 | |
367 | 300 | <!-- MODAL LINK EDIT--> |
368 | - {% if user|has_role:'system_admin' or topic.owner == user%} | |
301 | + {% professor_subject topic.subject user as links_update %} | |
302 | + {% if links_update%} | |
369 | 303 | {% include "links/update_link.html" %} |
370 | 304 | {% endif %} |
371 | 305 | ... | ... |
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,8 +39,9 @@ |
39 | 39 | <div class="col-md-10 col-sm-9"> |
40 | 40 | <h3>{{subject}}</h3> |
41 | 41 | </div> |
42 | - {% if user|has_role:'system_admin' or user in subject.professors %} | |
43 | - <div class="col-xs-4 col-md-2 divMoreActions"> | |
42 | + {% professor_subject subject user as subject_professor%} | |
43 | + {% if subject_professor %} | |
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"> |
46 | 47 | <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> |
... | ... | @@ -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,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
... | ... | @@ -2,6 +2,7 @@ from django import template |
2 | 2 | |
3 | 3 | from forum.models import Forum |
4 | 4 | from poll.models import Poll |
5 | +from files.models import TopicFile | |
5 | 6 | register = template.Library() |
6 | 7 | |
7 | 8 | """ |
... | ... | @@ -28,3 +29,25 @@ def list_topic_poll(request, topic): |
28 | 29 | context['topic'] = topic |
29 | 30 | |
30 | 31 | return context |
32 | + | |
33 | +@register.inclusion_tag('topic/list_file.html') | |
34 | +def list_topic_file(request, topic): | |
35 | + context = { | |
36 | + 'request': request, | |
37 | + } | |
38 | + | |
39 | + context['files'] = TopicFile.objects.filter(topic = topic) | |
40 | + context['topic'] = topic | |
41 | + | |
42 | + return context | |
43 | + | |
44 | +@register.inclusion_tag('topic/list_file_edit.html') | |
45 | +def list_topic_file_edit(request, topic): | |
46 | + context = { | |
47 | + 'request': request, | |
48 | + } | |
49 | + | |
50 | + context['files'] = TopicFile.objects.filter(topic = topic) | |
51 | + context['topic'] = topic | |
52 | + | |
53 | + 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
... | ... | @@ -28,6 +28,7 @@ urlpatterns = [ |
28 | 28 | url(r'^forum/', include('forum.urls', namespace = 'forum')), |
29 | 29 | url(r'^poll/', include('poll.urls', namespace = 'poll')), |
30 | 30 | url(r'^exam/', include('exam.urls', namespace = 'exam')), |
31 | + url(r'^files/', include('files.urls', namespace = 'file')), | |
31 | 32 | url(r'^upload-material/$', views.UploadMaterialView.as_view(), name='upload_material'), |
32 | 33 | |
33 | 34 | ... | ... |
courses/views.py
... | ... | @@ -40,9 +40,9 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView): |
40 | 40 | else: |
41 | 41 | list_courses = Course.objects.filter(students__name = self.request.user.name) |
42 | 42 | categorys_courses = CourseCategory.objects.filter(course_category__students__name = self.request.user.name).distinct() |
43 | - | |
43 | + | |
44 | 44 | courses_category = Course.objects.filter(category__name = self.request.GET.get('category')) |
45 | - | |
45 | + | |
46 | 46 | none = None |
47 | 47 | q = self.request.GET.get('category', None) |
48 | 48 | if q is None: |
... | ... | @@ -58,7 +58,7 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView): |
58 | 58 | list_courses = paginator.page(1) |
59 | 59 | except EmptyPage: |
60 | 60 | list_courses = paginator.page(paginator.num_pages) |
61 | - | |
61 | + | |
62 | 62 | context['courses_category'] = courses_category |
63 | 63 | context['list_courses'] = list_courses |
64 | 64 | context['categorys_courses'] = categorys_courses |
... | ... | @@ -74,7 +74,6 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView): |
74 | 74 | object_list = Course.objects.filter(name__icontains = name) |
75 | 75 | else: |
76 | 76 | object_list = Course.objects.all() |
77 | - print(object_list) | |
78 | 77 | return object_list |
79 | 78 | |
80 | 79 | class CreateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edit.CreateView): |
... | ... | @@ -159,7 +158,6 @@ class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): |
159 | 158 | elif has_role(self.request.user,'professor'): |
160 | 159 | courses = self.request.user.courses.all() |
161 | 160 | context['courses'] = courses |
162 | - print (courses,"jdhksjbjs") | |
163 | 161 | context['title'] = course.name |
164 | 162 | |
165 | 163 | return context |
... | ... | @@ -198,15 +196,15 @@ class CourseView(LoginRequiredMixin, NotificationMixin, generic.DetailView): |
198 | 196 | categorys_subjects = CategorySubject.objects.filter(subject_category__professors__name = self.request.user.name).distinct() |
199 | 197 | else: |
200 | 198 | categorys_subjects = CategorySubject.objects.filter(subject_category__students__name = self.request.user.name).distinct() |
201 | - | |
199 | + | |
202 | 200 | subjects_category = Subject.objects.filter(category__name = self.request.GET.get('category')) |
203 | - | |
201 | + | |
204 | 202 | none = None |
205 | 203 | q = self.request.GET.get('category', None) |
206 | 204 | if q is None: |
207 | 205 | none = True |
208 | 206 | context['none'] = none |
209 | - | |
207 | + | |
210 | 208 | context['subjects_category'] = subjects_category |
211 | 209 | context['categorys_subjects'] = categorys_subjects |
212 | 210 | context['courses'] = courses |
... | ... | @@ -330,14 +328,14 @@ class SubjectsView(LoginRequiredMixin, generic.ListView): |
330 | 328 | else: |
331 | 329 | context['files'] = TopicFile.objects.filter(students__name = self.request.user.name) |
332 | 330 | return context |
333 | - | |
331 | + | |
334 | 332 | class UploadMaterialView(LoginRequiredMixin, generic.edit.CreateView): |
335 | - login_url = reverse_lazy("core:home") | |
333 | + login_url = reverse_lazy("core:home") | |
336 | 334 | redirect_field_name = 'next' |
337 | 335 | |
338 | 336 | template_name = 'files/create_file.html' |
339 | 337 | form_class = FileForm |
340 | - | |
338 | + | |
341 | 339 | def form_invalid(self, form): |
342 | 340 | context = super(UploadMaterialView, self).form_invalid(form) |
343 | 341 | context.status_code = 400 |
... | ... | @@ -346,7 +344,7 @@ class UploadMaterialView(LoginRequiredMixin, generic.edit.CreateView): |
346 | 344 | |
347 | 345 | def get_success_url(self): |
348 | 346 | self.success_url = reverse('course:view_subject', args = (self.object.slug, )) |
349 | - | |
347 | + | |
350 | 348 | return self.success_url |
351 | 349 | |
352 | 350 | class TopicsView(LoginRequiredMixin, generic.ListView): | ... | ... |
exam/migrations/0001_initial.py
1 | 1 | # -*- coding: utf-8 -*- |
2 | -# Generated by Django 1.10 on 2016-10-17 15:49 | |
2 | +# Generated by Django 1.10 on 2016-10-18 02:47 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | 5 | from django.db import migrations, models |
... | ... | @@ -23,16 +23,16 @@ class Migration(migrations.Migration): |
23 | 23 | ('order', models.PositiveSmallIntegerField(verbose_name='Order')), |
24 | 24 | ], |
25 | 25 | options={ |
26 | - 'ordering': ('order',), | |
27 | 26 | 'verbose_name_plural': 'Answers', |
28 | 27 | 'verbose_name': 'Answer', |
28 | + 'ordering': ('order',), | |
29 | 29 | }, |
30 | 30 | ), |
31 | 31 | migrations.CreateModel( |
32 | 32 | name='Exam', |
33 | 33 | fields=[ |
34 | 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(verbose_name='Begin of Course Date')), | |
35 | + ('begin_date', models.DateField(blank=True, verbose_name='Begin of Course Date')), | |
36 | 36 | ], |
37 | 37 | options={ |
38 | 38 | 'verbose_name_plural': 'Exams', | ... | ... |
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/views.py
... | ... | @@ -67,7 +67,6 @@ class ViewExam(LoginRequiredMixin,generic.DetailView): |
67 | 67 | context['answers'] = answers |
68 | 68 | context['keys'] = keys |
69 | 69 | |
70 | - print (context) | |
71 | 70 | return context |
72 | 71 | |
73 | 72 | |
... | ... | @@ -170,7 +169,6 @@ class UpdateExam(LoginRequiredMixin,HasRoleMixin,generic.UpdateView): |
170 | 169 | |
171 | 170 | answers = {} |
172 | 171 | for answer in exam.answers.all(): |
173 | - # print (key.answer) | |
174 | 172 | answers[answer.order] = answer.answer |
175 | 173 | |
176 | 174 | 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-17 15:49 | |
2 | +# Generated by Django 1.10 on 2016-10-18 02:47 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | +from django.conf import settings | |
5 | 6 | from django.db import migrations, models |
6 | 7 | import django.db.models.deletion |
7 | 8 | import files.models |
... | ... | @@ -13,6 +14,7 @@ class Migration(migrations.Migration): |
13 | 14 | |
14 | 15 | dependencies = [ |
15 | 16 | ('courses', '0001_initial'), |
17 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
16 | 18 | ('core', '0001_initial'), |
17 | 19 | ] |
18 | 20 | |
... | ... | @@ -23,11 +25,13 @@ class Migration(migrations.Migration): |
23 | 25 | ('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 | 26 | ('description', models.TextField(blank=True, verbose_name='Description')), |
25 | 27 | ('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')), | |
28 | + ('file_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='topic_files', to='core.MimeType', verbose_name='Type file')), | |
29 | + ('professor', models.ManyToManyField(related_name='file_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors')), | |
27 | 30 | ], |
28 | 31 | options={ |
29 | 32 | 'verbose_name_plural': 'Files', |
30 | 33 | 'verbose_name': 'File', |
34 | + 'ordering': ('-id',), | |
31 | 35 | }, |
32 | 36 | bases=('courses.material',), |
33 | 37 | ), | ... | ... |
files/migrations/0002_topicfile_professor.py
... | ... | @@ -1,24 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-17 15:49 | |
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 | 5 | from users.models import User |
6 | 6 | |
... | ... | @@ -20,12 +20,13 @@ class TopicFile(Material): |
20 | 20 | professor = models.ManyToManyField(User,verbose_name=_('Professors'), related_name='file_professors') |
21 | 21 | description = models.TextField(_('Description'), blank=True) |
22 | 22 | file_url = models.FileField(verbose_name = _("File"), upload_to = file_path) |
23 | - 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') | |
24 | 24 | |
25 | 25 | |
26 | 26 | class Meta: |
27 | 27 | verbose_name = _("File") |
28 | 28 | verbose_name_plural = _("Files") |
29 | + ordering = ('-id',) | |
29 | 30 | |
30 | 31 | def __str__(self): |
31 | 32 | return self.name |
32 | 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 | -<form method="post" id="material_create" enctype="multipart/form-data" action="{% if material %}{% else %}{% url 'course:upload_material' %}{% endif %}"> | |
4 | - {% csrf_token %} | |
5 | - {% for field in form %} | |
6 | - <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput"> | |
7 | - {% if field.field.widget.input_type == 'hidden' %} | |
8 | - {% render_field field class='form-control' %} | |
9 | - {% else %} | |
10 | - {% if field.field.required %} | |
11 | - <label for="{{ field.auto_id }}" class="control-label">{{ field.label }}<span>*</span></label> | |
12 | - {% else %} | |
13 | - <label for="{{ field.auto_id }}" class=" control-label">{{ field.label }}</label> | |
14 | - {% endif %} | |
15 | - <label for="{{ field.auto_id }}">{{ field.label }}</label> | |
16 | - {% render_field field %} | |
17 | - <span class="help-block">{{ field.help_text }}</span> | |
18 | - {% if field.auto_id == 'id_file_url' %} | |
19 | - {% render_field field class='form-control input-sm' %} | |
20 | - <div class="input-group"> | |
21 | - <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your file...' %}"> | |
22 | - <span class="input-group-btn input-group-sm"> | |
23 | - <button type="button" class="btn btn-fab btn-fab-mini"> | |
24 | - <i class="material-icons">attach_file</i> | |
25 | - </button> | |
26 | - </span> | |
27 | - </div> | |
28 | - {% else %} | |
29 | - {% render_field field class='form-control input-sm' %} | |
30 | - <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
31 | - {% endif %} | |
32 | - {% if field.errors %} | |
33 | - <div class="row"> | |
34 | - <br /> | |
35 | - <div class="alert alert-danger alert-dismissible" role="alert"> | |
36 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
37 | - <span aria-hidden="true">×</span> | |
38 | - </button> | |
39 | - <ul> | |
40 | - {% for error in field.errors %} | |
41 | - <li>{{ error }}</li> | |
42 | - {% endfor %} | |
43 | - </ul> | |
44 | - </div> | |
45 | - </div> | |
46 | - {% endif %} | |
47 | - {% endif %} | |
3 | +<!-- MODAL CREATE FILE --> | |
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> | |
61 | + </div> | |
62 | + {% endif %} | |
63 | + </div> | |
64 | + {% endfor %} | |
65 | + | |
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> | |
70 | + </div> | |
71 | + | |
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> | |
77 | + </div> | |
78 | + </fieldset> | |
79 | + </form> | |
80 | + <!-- .end Card --> | |
81 | + </div> | |
82 | + </div> | |
48 | 83 | </div> |
49 | - {% endfor %} | |
50 | -</form> | |
51 | -<!-- EndModal --> | |
52 | 84 | \ No newline at end of file |
85 | + </div> | |
86 | +</div> | |
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 %} | |
53 | 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-17 15:49 | |
2 | +# Generated by Django 1.10 on 2016-10-18 02:48 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | +from django.conf import settings | |
5 | 6 | from django.db import migrations, models |
6 | 7 | import django.db.models.deletion |
7 | 8 | |
... | ... | @@ -11,6 +12,7 @@ class Migration(migrations.Migration): |
11 | 12 | initial = True |
12 | 13 | |
13 | 14 | dependencies = [ |
15 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
14 | 16 | ('courses', '0001_initial'), |
15 | 17 | ] |
16 | 18 | |
... | ... | @@ -24,8 +26,8 @@ class Migration(migrations.Migration): |
24 | 26 | ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Create Date')), |
25 | 27 | ], |
26 | 28 | options={ |
27 | - 'verbose_name_plural': 'Foruns', | |
28 | 29 | 'verbose_name': 'Forum', |
30 | + 'verbose_name_plural': 'Foruns', | |
29 | 31 | }, |
30 | 32 | bases=('courses.activity',), |
31 | 33 | ), |
... | ... | @@ -36,10 +38,12 @@ class Migration(migrations.Migration): |
36 | 38 | ('message', models.TextField(verbose_name='Post message')), |
37 | 39 | ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')), |
38 | 40 | ('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')), | |
39 | 43 | ], |
40 | 44 | options={ |
41 | - 'verbose_name_plural': 'Posts', | |
42 | 45 | 'verbose_name': 'Post', |
46 | + 'verbose_name_plural': 'Posts', | |
43 | 47 | }, |
44 | 48 | ), |
45 | 49 | migrations.CreateModel( |
... | ... | @@ -50,10 +54,11 @@ class Migration(migrations.Migration): |
50 | 54 | ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')), |
51 | 55 | ('answer_date', models.DateTimeField(auto_now_add=True, verbose_name='Answer Date')), |
52 | 56 | ('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')), | |
53 | 58 | ], |
54 | 59 | options={ |
55 | - 'verbose_name_plural': 'Post Answers', | |
56 | 60 | 'verbose_name': 'Post Answer', |
61 | + 'verbose_name_plural': 'Post Answers', | |
57 | 62 | }, |
58 | 63 | ), |
59 | 64 | ] | ... | ... |
forum/migrations/0002_auto_20161017_1249.py
... | ... | @@ -1,35 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-17 15:49 | |
3 | -from __future__ import unicode_literals | |
4 | - | |
5 | -from django.conf import settings | |
6 | -from django.db import migrations, models | |
7 | -import django.db.models.deletion | |
8 | - | |
9 | - | |
10 | -class Migration(migrations.Migration): | |
11 | - | |
12 | - initial = True | |
13 | - | |
14 | - dependencies = [ | |
15 | - ('forum', '0001_initial'), | |
16 | - migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
17 | - ] | |
18 | - | |
19 | - operations = [ | |
20 | - migrations.AddField( | |
21 | - model_name='postanswer', | |
22 | - name='user', | |
23 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor'), | |
24 | - ), | |
25 | - migrations.AddField( | |
26 | - model_name='post', | |
27 | - name='forum', | |
28 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Forum', verbose_name='Forum'), | |
29 | - ), | |
30 | - migrations.AddField( | |
31 | - model_name='post', | |
32 | - name='user', | |
33 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor'), | |
34 | - ), | |
35 | - ] |
links/migrations/0001_initial.py
poll/migrations/0001_initial.py
1 | 1 | # -*- coding: utf-8 -*- |
2 | -# Generated by Django 1.10 on 2016-10-17 15:49 | |
2 | +# Generated by Django 1.10 on 2016-10-18 02:47 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | +from django.conf import settings | |
5 | 6 | from django.db import migrations, models |
6 | 7 | import django.db.models.deletion |
7 | 8 | |
... | ... | @@ -12,6 +13,7 @@ class Migration(migrations.Migration): |
12 | 13 | |
13 | 14 | dependencies = [ |
14 | 15 | ('courses', '0001_initial'), |
16 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
15 | 17 | ] |
16 | 18 | |
17 | 19 | operations = [ |
... | ... | @@ -23,9 +25,9 @@ class Migration(migrations.Migration): |
23 | 25 | ('order', models.PositiveSmallIntegerField(verbose_name='Order')), |
24 | 26 | ], |
25 | 27 | options={ |
26 | - 'ordering': ('order',), | |
27 | 28 | 'verbose_name_plural': 'Answers', |
28 | 29 | 'verbose_name': 'Answer', |
30 | + 'ordering': ('order',), | |
29 | 31 | }, |
30 | 32 | ), |
31 | 33 | migrations.CreateModel( |
... | ... | @@ -57,4 +59,14 @@ class Migration(migrations.Migration): |
57 | 59 | name='poll', |
58 | 60 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundet', to='poll.Poll', verbose_name='Poll'), |
59 | 61 | ), |
62 | + migrations.AddField( | |
63 | + model_name='answersstudent', | |
64 | + name='student', | |
65 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundent', to=settings.AUTH_USER_MODEL, verbose_name='Student'), | |
66 | + ), | |
67 | + migrations.AddField( | |
68 | + model_name='answer', | |
69 | + name='poll', | |
70 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='poll.Poll', verbose_name='Answers'), | |
71 | + ), | |
60 | 72 | ] | ... | ... |
poll/migrations/0002_auto_20161017_1249.py
... | ... | @@ -1,30 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-10-17 15:49 | |
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/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) | ... | ... |