Commit a4c22c10e5b9a202d86ff3a59efac08728605aa7

Authored by Matheus Lins
2 parents e8b64ae0 e6034fe7

fixing conflit

Showing 68 changed files with 1242 additions and 752 deletions   Show diff stats
amadeus/roles.py
@@ -24,4 +24,4 @@ class Professor(AbstractUserRole): @@ -24,4 +24,4 @@ class Professor(AbstractUserRole):
24 } 24 }
25 25
26 class SystemAdmin(AbstractUserRole): 26 class SystemAdmin(AbstractUserRole):
27 - pass  
28 \ No newline at end of file 27 \ No newline at end of file
  28 + pass
amadeus/settings.py
@@ -224,6 +224,9 @@ S3DIRECT_DESTINATIONS = { @@ -224,6 +224,9 @@ S3DIRECT_DESTINATIONS = {
224 224
225 } 225 }
226 226
  227 +# FILE UPLOAD
  228 +MAX_UPLOAD_SIZE = 10485760
  229 +
227 try: 230 try:
228 from .local_settings import * 231 from .local_settings import *
229 except ImportError: 232 except ImportError:
amadeus/staticfiles/js/modal_poll.js 0 → 100644
@@ -0,0 +1,43 @@ @@ -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");
amadeus/staticfiles/js/modals_requisitions.js 0 → 100644
@@ -0,0 +1,14 @@ @@ -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");
amadeus/staticfiles/js/sortable_poll.js 0 → 100644
@@ -0,0 +1,12 @@ @@ -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,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 \ No newline at end of file 0 \ No newline at end of file
app/templates/app/index.html
@@ -1,181 +0,0 @@ @@ -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 %}  
1 from django.contrib import admin 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 class ActionAdmin(admin.ModelAdmin): 4 class ActionAdmin(admin.ModelAdmin):
6 list_display = ['name', 'created_date'] 5 list_display = ['name', 'created_date']
@@ -18,7 +17,7 @@ class LogAdmin(admin.ModelAdmin): @@ -18,7 +17,7 @@ class LogAdmin(admin.ModelAdmin):
18 list_display = ['datetime', 'user', 'action_resource'] 17 list_display = ['datetime', 'user', 'action_resource']
19 search_fields = ['user'] 18 search_fields = ['user']
20 19
21 -class MymeTypeAdmin(admin.ModelAdmin): 20 +class MimeTypeAdmin(admin.ModelAdmin):
22 list_display = ['typ', 'icon'] 21 list_display = ['typ', 'icon']
23 search_fields = ['typ', 'icon'] 22 search_fields = ['typ', 'icon']
24 23
@@ -26,4 +25,4 @@ admin.site.register(Action, ActionAdmin) @@ -26,4 +25,4 @@ admin.site.register(Action, ActionAdmin)
26 admin.site.register(Resource, ResourceAdmin) 25 admin.site.register(Resource, ResourceAdmin)
27 admin.site.register(Action_Resource, ActionResourceAdmin) 26 admin.site.register(Action_Resource, ActionResourceAdmin)
28 admin.site.register(Log, LogAdmin) 27 admin.site.register(Log, LogAdmin)
29 -admin.site.register(MymeType, MymeTypeAdmin)  
30 \ No newline at end of file 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 = &#39;&#39;, log_resource = &#39;&#39;): @@ -48,16 +48,15 @@ def log_decorator(log_action = &#39;&#39;, log_resource = &#39;&#39;):
48 48
49 49
50 def notification_decorator(read = False, message = '', actor = None, users = [], not_action='', not_resource='', resource_link=''): 50 def notification_decorator(read = False, message = '', actor = None, users = [], not_action='', not_resource='', resource_link=''):
51 - 51 +
52 def _notification_decorator(view_function): 52 def _notification_decorator(view_function):
53 53
54 def _decorator(request, *args, **kwargs): 54 def _decorator(request, *args, **kwargs):
55 #Do something before the call 55 #Do something before the call
56 - 56 +
57 response = view_function(request, *args, **kwargs) 57 response = view_function(request, *args, **kwargs)
58 action = Action.objects.filter(name = not_action) 58 action = Action.objects.filter(name = not_action)
59 resource = Resource.objects.filter(name = not_resource) 59 resource = Resource.objects.filter(name = not_resource)
60 - print(resource_link)  
61 if action.exists(): 60 if action.exists():
62 action = action[0] 61 action = action[0]
63 else: 62 else:
@@ -68,7 +67,6 @@ def notification_decorator(read = False, message = &#39;&#39;, actor = None, users = [], @@ -68,7 +67,6 @@ def notification_decorator(read = False, message = &#39;&#39;, actor = None, users = [],
68 resource = resource[0] 67 resource = resource[0]
69 else: 68 else:
70 resource = Resource(name = not_resource, url= resource_link) 69 resource = Resource(name = not_resource, url= resource_link)
71 - print(resource)  
72 resource.save() 70 resource.save()
73 71
74 action_resource = Action_Resource.objects.filter(action = action, resource = resource) 72 action_resource = Action_Resource.objects.filter(action = action, resource = resource)
@@ -82,11 +80,11 @@ def notification_decorator(read = False, message = &#39;&#39;, actor = None, users = [], @@ -82,11 +80,11 @@ def notification_decorator(read = False, message = &#39;&#39;, actor = None, users = [],
82 for user in users: 80 for user in users:
83 notification = Notification(user=user, actor= actor, message=message, action_resource= action_resource) 81 notification = Notification(user=user, actor= actor, message=message, action_resource= action_resource)
84 notification.save() 82 notification.save()
85 -  
86 - 83 +
  84 +
87 #Do something after the call 85 #Do something after the call
88 return response 86 return response
89 87
90 return wraps(view_function)(_decorator) 88 return wraps(view_function)(_decorator)
91 -  
92 - return _notification_decorator  
93 \ No newline at end of file 89 \ No newline at end of file
  90 +
  91 + return _notification_decorator
core/migrations/0001_initial.py
1 # -*- coding: utf-8 -*- 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 from __future__ import unicode_literals 3 from __future__ import unicode_literals
4 4
5 import autoslug.fields 5 import autoslug.fields
  6 +from django.conf import settings
6 from django.db import migrations, models 7 from django.db import migrations, models
7 import django.db.models.deletion 8 import django.db.models.deletion
8 9
@@ -12,6 +13,7 @@ class Migration(migrations.Migration): @@ -12,6 +13,7 @@ class Migration(migrations.Migration):
12 initial = True 13 initial = True
13 14
14 dependencies = [ 15 dependencies = [
  16 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15 ] 17 ]
16 18
17 operations = [ 19 operations = [
@@ -23,18 +25,19 @@ class Migration(migrations.Migration): @@ -23,18 +25,19 @@ class Migration(migrations.Migration):
23 ('created_date', models.DateField(auto_now_add=True, verbose_name='Created Date')), 25 ('created_date', models.DateField(auto_now_add=True, verbose_name='Created Date')),
24 ], 26 ],
25 options={ 27 options={
26 - 'verbose_name_plural': 'Actions',  
27 'verbose_name': 'Action', 28 'verbose_name': 'Action',
  29 + 'verbose_name_plural': 'Actions',
28 }, 30 },
29 ), 31 ),
30 migrations.CreateModel( 32 migrations.CreateModel(
31 name='Action_Resource', 33 name='Action_Resource',
32 fields=[ 34 fields=[
33 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 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 options={ 38 options={
36 - 'verbose_name_plural': 'Action_Resources',  
37 'verbose_name': 'Action_Resource', 39 'verbose_name': 'Action_Resource',
  40 + 'verbose_name_plural': 'Action_Resources',
38 }, 41 },
39 ), 42 ),
40 migrations.CreateModel( 43 migrations.CreateModel(
@@ -42,22 +45,24 @@ class Migration(migrations.Migration): @@ -42,22 +45,24 @@ class Migration(migrations.Migration):
42 fields=[ 45 fields=[
43 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 46 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
44 ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), 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 options={ 51 options={
47 - 'verbose_name_plural': 'Logs',  
48 'verbose_name': 'Log', 52 'verbose_name': 'Log',
  53 + 'verbose_name_plural': 'Logs',
49 }, 54 },
50 ), 55 ),
51 migrations.CreateModel( 56 migrations.CreateModel(
52 - name='MymeType', 57 + name='MimeType',
53 fields=[ 58 fields=[
54 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 59 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
55 ('typ', models.CharField(max_length=100, unique=True, verbose_name='Type')), 60 ('typ', models.CharField(max_length=100, unique=True, verbose_name='Type')),
56 ('icon', models.CharField(max_length=50, unique=True, verbose_name='Icon')), 61 ('icon', models.CharField(max_length=50, unique=True, verbose_name='Icon')),
57 ], 62 ],
58 options={ 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 migrations.CreateModel( 68 migrations.CreateModel(
@@ -68,10 +73,12 @@ class Migration(migrations.Migration): @@ -68,10 +73,12 @@ class Migration(migrations.Migration):
68 ('read', models.BooleanField(default=False, verbose_name='Read')), 73 ('read', models.BooleanField(default=False, verbose_name='Read')),
69 ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), 74 ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')),
70 ('action_resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource')), 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 options={ 79 options={
73 - 'verbose_name_plural': 'Notifications',  
74 'verbose_name': 'Notification', 80 'verbose_name': 'Notification',
  81 + 'verbose_name_plural': 'Notifications',
75 }, 82 },
76 ), 83 ),
77 migrations.CreateModel( 84 migrations.CreateModel(
@@ -84,8 +91,13 @@ class Migration(migrations.Migration): @@ -84,8 +91,13 @@ class Migration(migrations.Migration):
84 ('url', models.CharField(default='', max_length=100, verbose_name='URL')), 91 ('url', models.CharField(default='', max_length=100, verbose_name='URL')),
85 ], 92 ],
86 options={ 93 options={
87 - 'verbose_name_plural': 'Resources',  
88 'verbose_name': 'Resource', 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,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,7 +47,6 @@ class NotificationMixin(object):
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 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 action = Action.objects.filter(name = action_name) 48 action = Action.objects.filter(name = action_name)
49 resource = Resource.objects.filter(slug = resource_slug) 49 resource = Resource.objects.filter(slug = resource_slug)
50 - print(message)  
51 if action.exists(): 50 if action.exists():
52 action = action[0] 51 action = action[0]
53 else: 52 else:
@@ -76,5 +75,4 @@ class NotificationMixin(object): @@ -76,5 +75,4 @@ class NotificationMixin(object):
76 def dispatch(self, request, *args, **kwargs): 75 def dispatch(self, request, *args, **kwargs):
77 """ 76 """
78 Not quite sure how to do about it""" 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 \ No newline at end of file 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,13 +4,13 @@ from users.models import User
4 from autoslug.fields import AutoSlugField 4 from autoslug.fields import AutoSlugField
5 # Create your models here. 5 # Create your models here.
6 6
7 -class MymeType(models.Model): 7 +class MimeType(models.Model):
8 typ = models.CharField(_('Type'), max_length=100, unique=True) 8 typ = models.CharField(_('Type'), max_length=100, unique=True)
9 icon = models.CharField(_('Icon'), max_length=50, unique=True) 9 icon = models.CharField(_('Icon'), max_length=50, unique=True)
10 10
11 class Meta: 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 def get_icon(self, type): 15 def get_icon(self, type):
16 pass 16 pass
core/static/css/base/.fuse_hidden0000098e00000001 0 → 100644
@@ -0,0 +1,315 @@ @@ -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
  1 +.clearfix{
  2 + clear: both;
  3 +}
  4 +
1 .navbar .logo {position: absolute; top: 6px; text-align: center; height: 48px; width: 48px;} 5 .navbar .logo {position: absolute; top: 6px; text-align: center; height: 48px; width: 48px;}
2 6
3 /* Modal */ 7 /* Modal */
core/templates/base.html
@@ -116,6 +116,9 @@ @@ -116,6 +116,9 @@
116 </div> 116 </div>
117 <script src="{% static 'js/main.js' %}"></script> 117 <script src="{% static 'js/main.js' %}"></script>
118 <script type="text/javascript" src="{% static 'js/topic_editation_presentation.js' %}"></script> 118 <script type="text/javascript" src="{% static 'js/topic_editation_presentation.js' %}"></script>
  119 + {% block script_file %}
  120 +
  121 + {% endblock script_file %}
119 </body> 122 </body>
120 123
121 </html> 124 </html>
@@ -102,7 +102,7 @@ def processNotification(self, notificationId): @@ -102,7 +102,7 @@ def processNotification(self, notificationId):
102 def getNotifications(request): 102 def getNotifications(request):
103 context = {} 103 context = {}
104 if request.user.is_authenticated: 104 if request.user.is_authenticated:
105 - 105 +
106 steps = int(request.GET['steps']) 106 steps = int(request.GET['steps'])
107 amount = int(request.GET['amount']) 107 amount = int(request.GET['amount'])
108 notifications = Notification.objects.filter(user= request.user, read=False).order_by('-datetime')[steps:steps+amount] 108 notifications = Notification.objects.filter(user= request.user, read=False).order_by('-datetime')[steps:steps+amount]
@@ -110,18 +110,6 @@ def getNotifications(request): @@ -110,18 +110,6 @@ def getNotifications(request):
110 else: #go to login page 110 else: #go to login page
111 return HttpResponse('teste') 111 return HttpResponse('teste')
112 112
113 - 113 +
114 html = render_to_string("notifications.html", context) 114 html = render_to_string("notifications.html", context)
115 - print(html)  
116 return HttpResponse(html) 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 # -*- coding: utf-8 -*- 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 from __future__ import unicode_literals 3 from __future__ import unicode_literals
4 4
5 import autoslug.fields 5 import autoslug.fields
  6 +from django.conf import settings
6 from django.db import migrations, models 7 from django.db import migrations, models
7 import django.db.models.deletion 8 import django.db.models.deletion
8 import s3direct.fields 9 import s3direct.fields
@@ -14,6 +15,7 @@ class Migration(migrations.Migration): @@ -14,6 +15,7 @@ class Migration(migrations.Migration):
14 15
15 dependencies = [ 16 dependencies = [
16 ('core', '0001_initial'), 17 ('core', '0001_initial'),
  18 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
17 ] 19 ]
18 20
19 operations = [ 21 operations = [
@@ -23,6 +25,7 @@ class Migration(migrations.Migration): @@ -23,6 +25,7 @@ class Migration(migrations.Migration):
23 ('resource_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.Resource')), 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 ('limit_date', models.DateField(verbose_name='Deliver Date')), 26 ('limit_date', models.DateField(verbose_name='Deliver Date')),
25 ('all_students', models.BooleanField(default=False, verbose_name='All Students')), 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 bases=('core.resource',), 30 bases=('core.resource',),
28 ), 31 ),
@@ -32,6 +35,7 @@ class Migration(migrations.Migration): @@ -32,6 +35,7 @@ class Migration(migrations.Migration):
32 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 35 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
33 ('pdf', s3direct.fields.S3DirectField()), 36 ('pdf', s3direct.fields.S3DirectField()),
34 ('name', models.CharField(max_length=100)), 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 options={ 40 options={
37 'verbose_name_plural': 'Activitys Files', 41 'verbose_name_plural': 'Activitys Files',
@@ -68,8 +72,8 @@ class Migration(migrations.Migration): @@ -68,8 +72,8 @@ class Migration(migrations.Migration):
68 ('image', models.ImageField(blank=True, upload_to='courses/', verbose_name='Image')), 72 ('image', models.ImageField(blank=True, upload_to='courses/', verbose_name='Image')),
69 ], 73 ],
70 options={ 74 options={
71 - 'ordering': ('create_date', 'name'),  
72 'verbose_name_plural': 'Courses', 75 'verbose_name_plural': 'Courses',
  76 + 'ordering': ('create_date', 'name'),
73 'verbose_name': 'Course', 77 'verbose_name': 'Course',
74 }, 78 },
75 ), 79 ),
@@ -108,6 +112,7 @@ class Migration(migrations.Migration): @@ -108,6 +112,7 @@ class Migration(migrations.Migration):
108 fields=[ 112 fields=[
109 ('resource_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.Resource')), 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 ('all_students', models.BooleanField(default=False, verbose_name='All Students')), 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 bases=('core.resource',), 117 bases=('core.resource',),
113 ), 118 ),
@@ -123,10 +128,14 @@ class Migration(migrations.Migration): @@ -123,10 +128,14 @@ class Migration(migrations.Migration):
123 ('end_date', models.DateField(verbose_name='End of Subject Date')), 128 ('end_date', models.DateField(verbose_name='End of Subject Date')),
124 ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), 129 ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')),
125 ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), 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 options={ 136 options={
128 - 'ordering': ('create_date', 'name'),  
129 'verbose_name_plural': 'Subjects', 137 'verbose_name_plural': 'Subjects',
  138 + 'ordering': ('create_date', 'name'),
130 'verbose_name': 'Subject', 139 'verbose_name': 'Subject',
131 }, 140 },
132 ), 141 ),
@@ -137,6 +146,7 @@ class Migration(migrations.Migration): @@ -137,6 +146,7 @@ class Migration(migrations.Migration):
137 ('name', models.CharField(max_length=100, verbose_name='Name')), 146 ('name', models.CharField(max_length=100, verbose_name='Name')),
138 ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')), 147 ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')),
139 ('description', models.TextField(blank=True, verbose_name='Description')), 148 ('description', models.TextField(blank=True, verbose_name='Description')),
  149 + ('subjects', models.ManyToManyField(to='courses.Subject')),
140 ], 150 ],
141 options={ 151 options={
142 'verbose_name_plural': 'subject categories', 152 'verbose_name_plural': 'subject categories',
@@ -153,11 +163,48 @@ class Migration(migrations.Migration): @@ -153,11 +163,48 @@ class Migration(migrations.Migration):
153 ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), 163 ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')),
154 ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), 164 ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')),
155 ('visible', models.BooleanField(default=False, verbose_name='Visible')), 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 options={ 169 options={
158 - 'ordering': ('create_date', 'name'),  
159 'verbose_name_plural': 'Topics', 170 'verbose_name_plural': 'Topics',
  171 + 'ordering': ('create_date', 'name'),
160 'verbose_name': 'Topic', 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,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,7 +2,7 @@ from django.utils.translation import ugettext_lazy as _
2 from django.db import models 2 from django.db import models
3 from autoslug.fields import AutoSlugField 3 from autoslug.fields import AutoSlugField
4 from users.models import User 4 from users.models import User
5 -from core.models import Resource, MymeType 5 +from core.models import Resource, MimeType
6 from s3direct.fields import S3DirectField 6 from s3direct.fields import S3DirectField
7 7
8 class CourseCategory(models.Model): 8 class CourseCategory(models.Model):
courses/templates/category/create.html
1 -{% extends 'app/base.html' %} 1 +{% extends 'base.html' %}
2 2
3 {% load static i18n permission_tags %} 3 {% load static i18n permission_tags %}
4 {% load widget_tweaks %} 4 {% load widget_tweaks %}
@@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
23 </div> 23 </div>
24 </div> 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 <div class="panel panel-primary navigation"> 28 <div class="panel panel-primary navigation">
29 <div class="panel-heading"> 29 <div class="panel-heading">
courses/templates/category/delete.html
1 -{% extends 'app/base.html' %} 1 +{% extends 'base.html' %}
2 2
3 {% load static i18n %} 3 {% load static i18n %}
4 {% load static i18n permission_tags %} 4 {% load static i18n permission_tags %}
@@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
23 </div> 23 </div>
24 </div> 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 <div class="panel panel-primary navigation"> 28 <div class="panel panel-primary navigation">
29 <div class="panel-heading"> 29 <div class="panel-heading">
courses/templates/category/index.html
1 -{% extends 'app/base.html' %} 1 +{% extends 'base.html' %}
2 2
3 {% load static i18n %} 3 {% load static i18n %}
4 {% load static i18n permission_tags %} 4 {% load static i18n permission_tags %}
@@ -23,8 +23,8 @@ @@ -23,8 +23,8 @@
23 </ul> 23 </ul>
24 </div> 24 </div>
25 </div> 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 <div class="panel panel-primary navigation"> 29 <div class="panel panel-primary navigation">
30 <div class="panel-heading"> 30 <div class="panel-heading">
courses/templates/category/update.html
1 -{% extends 'app/base.html' %} 1 +{% extends 'base.html' %}
2 2
3 {% load static i18n %} 3 {% load static i18n %}
4 {% load static i18n permission_tags %} 4 {% load static i18n permission_tags %}
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 </div> 24 </div>
25 </div> 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 <div class="panel panel-primary navigation"> 29 <div class="panel panel-primary navigation">
30 <div class="panel-heading"> 30 <div class="panel-heading">
@@ -87,7 +87,7 @@ @@ -87,7 +87,7 @@
87 {% endif %} 87 {% endif %}
88 {% endfor %} 88 {% endfor %}
89 <div class="row text-center"> 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 </div> 91 </div>
92 </form> 92 </form>
93 </div> 93 </div>
courses/templates/category/view.html
1 -{% extends 'app/base.html' %} 1 +{% extends 'base.html' %}
2 2
3 {% load static i18n permission_tags %} 3 {% load static i18n permission_tags %}
4 {% load widget_tweaks %} 4 {% load widget_tweaks %}
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 </ul> 24 </ul>
25 </div> 25 </div>
26 </div> 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 <div class="panel panel-primary navigation"> 29 <div class="panel panel-primary navigation">
30 <div class="panel-heading"> 30 <div class="panel-heading">
courses/templates/course/index.html
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 </div> 24 </div>
25 </div> 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 <div class="panel panel-primary navigation"> 29 <div class="panel panel-primary navigation">
30 <div class="panel-heading"> 30 <div class="panel-heading">
@@ -76,7 +76,7 @@ @@ -76,7 +76,7 @@
76 <i class="material-icons">search</i> 76 <i class="material-icons">search</i>
77 </button> 77 </button>
78 </span> 78 </span>
79 - </div> 79 + </div>
80 </form> 80 </form>
81 </div> 81 </div>
82 <div class="col-md-12"> 82 <div class="col-md-12">
@@ -103,7 +103,7 @@ @@ -103,7 +103,7 @@
103 <h4 style="color:white">{{course.name}}</h4> 103 <h4 style="color:white">{{course.name}}</h4>
104 </a> 104 </a>
105 </div> 105 </div>
106 - {% if user|has_role:'professor, system_admin' %} 106 + {% if user|has_role:'professor' or user|has_role:'system_admin' %}
107 <div class="col-xs-4 col-md-3" id="divMoreActions"> 107 <div class="col-xs-4 col-md-3" id="divMoreActions">
108 <div class="btn-group"> 108 <div class="btn-group">
109 <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> 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,7 +150,7 @@
150 <h4 style="color:white">{{course.name}}</h4> 150 <h4 style="color:white">{{course.name}}</h4>
151 </a> 151 </a>
152 </div> 152 </div>
153 - {% if user|has_role:'professor, system_admin' %} 153 + {% if user|has_role:'professor' or user|has_role:'system_admin' %}
154 <div class="col-xs-4 col-md-3" id="divMoreActions"> 154 <div class="col-xs-4 col-md-3" id="divMoreActions">
155 <div class="btn-group"> 155 <div class="btn-group">
156 <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> 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,7 +28,7 @@
28 </div> 28 </div>
29 </div> 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 <div class="panel panel-primary navigation"> 33 <div class="panel panel-primary navigation">
34 <div class="panel-heading"> 34 <div class="panel-heading">
@@ -282,7 +282,7 @@ @@ -282,7 +282,7 @@
282 {% endif %} 282 {% endif %}
283 283
284 {% if user|has_role:'professor' or user|has_role:'system_admin' %} 284 {% if user|has_role:'professor' or user|has_role:'system_admin' %}
285 - 285 +
286 <div class="form-group"> 286 <div class="form-group">
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> 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 </div> 288 </div>
@@ -314,4 +314,3 @@ @@ -314,4 +314,3 @@
314 </div> 314 </div>
315 315
316 {% endblock %} 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 {% block javascript %} 3 {% block javascript %}
4 <script type="text/javascript" src="{% static 'js/forum.js' %}"></script> 4 <script type="text/javascript" src="{% static 'js/forum.js' %}"></script>
  5 + <script src="{% static 'js/file.js' %}"></script>
5 <script type="text/javascript" src="{% static 'js/material.js' %}"></script> 6 <script type="text/javascript" src="{% static 'js/material.js' %}"></script>
  7 + <script type = "text/javascript" src="{% static 'link.js' %}"></script>
6 {% endblock %} 8 {% endblock %}
7 9
8 <div class="panel-group accordion ui-accordion ui-widget ui-helper-reset ui-sortable" role="tablist" aria-multiselectable="false"> 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,7 +26,8 @@
24 <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> 26 <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
25 <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> 27 <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
26 </button> 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 <ul class="dropdown-menu pull-right" aria-labelledby="moreActions"> 31 <ul class="dropdown-menu pull-right" aria-labelledby="moreActions">
29 <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal4"><i class="fa fa-files-o fa-fw" aria-hidden="true"></i>&nbsp; {% trans "Replicate" %}</a></li> 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>&nbsp; {% trans "Replicate" %}</a></li>
30 <li><a href="javascript:void(0)" class="edit_card"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i>&nbsp; {% trans "Edit" %}</a></li> 33 <li><a href="javascript:void(0)" class="edit_card"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i>&nbsp; {% trans "Edit" %}</a></li>
@@ -52,18 +55,23 @@ @@ -52,18 +55,23 @@
52 <div class="dropdown"> 55 <div class="dropdown">
53 <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> 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 <ul class="dropdown-menu" aria-labelledby="dLabel"> 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 </ul> 68 </ul>
58 </div> 69 </div>
59 </div> 70 </div>
60 <ul> 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 </ul> 75 </ul>
68 </div> 76 </div>
69 <div class="col-xs-4 col-md-4"> 77 <div class="col-xs-4 col-md-4">
@@ -106,18 +114,14 @@ @@ -106,18 +114,14 @@
106 <div class="dropdown"> 114 <div class="dropdown">
107 <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> 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 <ul class="dropdown-menu" aria-labelledby="dLabel"> 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 </ul> 119 </ul>
112 </div> 120 </div>
113 </div> 121 </div>
114 <ul> 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 </ul> 125 </ul>
122 </div> 126 </div>
123 <div class="col-xs-4 col-md-offset-1 col-md-4"> 127 <div class="col-xs-4 col-md-offset-1 col-md-4">
@@ -129,6 +133,7 @@ @@ -129,6 +133,7 @@
129 <a href="#" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-plus-circle fa-lg" aria-hidden="true"></i></a> 133 <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 <ul class="dropdown-menu" aria-labelledby="dLabel"> 134 <ul class="dropdown-menu" aria-labelledby="dLabel">
131 <li>Qualquer coisa</li> 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 </ul> 137 </ul>
133 </div> 138 </div>
134 </div> 139 </div>
@@ -171,81 +176,9 @@ @@ -171,81 +176,9 @@
171 </div> 176 </div>
172 </div> 177 </div>
173 <!-- END --> 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 {% include "links/create_link.html" %} 181 {% include "links/create_link.html" %}
246 - {% endif %}  
247 -  
248 - {% if user|has_role:'system_admin' or topic.owner == user%}  
249 {% include "links/delete_link.html" %} 182 {% include "links/delete_link.html" %}
250 {% endif %} 183 {% endif %}
251 184
@@ -365,7 +298,8 @@ @@ -365,7 +298,8 @@
365 298
366 299
367 <!-- MODAL LINK EDIT--> 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 {% include "links/update_link.html" %} 303 {% include "links/update_link.html" %}
370 {% endif %} 304 {% endif %}
371 305
courses/templates/subject/index.html
1 {% extends 'base.html' %} 1 {% extends 'base.html' %}
2 2
3 -{% load static i18n permission_tags %} 3 +{% load static i18n permission_tags professor_access %}
4 4
5 {% block breadcrumbs %} 5 {% block breadcrumbs %}
6 6
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 {% else %} 12 {% else %}
13 <li class="active">{{ subject.name }}</li> 13 <li class="active">{{ subject.name }}</li>
14 {% endif %} 14 {% endif %}
15 - 15 +
16 </ol> 16 </ol>
17 {% endblock %} 17 {% endblock %}
18 18
@@ -28,7 +28,7 @@ @@ -28,7 +28,7 @@
28 </ul> 28 </ul>
29 </div> 29 </div>
30 </div> 30 </div>
31 - 31 +
32 32
33 {% endblock %} 33 {% endblock %}
34 34
@@ -39,8 +39,9 @@ @@ -39,8 +39,9 @@
39 <div class="col-md-10 col-sm-9"> 39 <div class="col-md-10 col-sm-9">
40 <h3>{{subject}}</h3> 40 <h3>{{subject}}</h3>
41 </div> 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 <div class="btn-group"> 45 <div class="btn-group">
45 <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> 46 <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
46 <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> 47 <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
@@ -71,19 +72,20 @@ @@ -71,19 +72,20 @@
71 </div> 72 </div>
72 </div> 73 </div>
73 </div> 74 </div>
74 - 75 +
75 {% for topic in topics %} 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 {% include "subject/form_view_teacher.html" %} 79 {% include "subject/form_view_teacher.html" %}
78 {% else %} 80 {% else %}
79 {% include "subject/form_view_student.html" %} 81 {% include "subject/form_view_student.html" %}
80 {% endif %} 82 {% endif %}
81 {% endfor %} 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 <div class="form-group"> 86 <div class="form-group">
85 <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> 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 </div> 88 </div>
87 - {% endif %} 89 + {% endif %}
88 90
89 {% endblock %} 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 <script src="{% static 'js/modals_requisitions.js'%}"></script> 3 <script src="{% static 'js/modals_requisitions.js'%}"></script>
4 <script src="{% static 'js/modal_poll.js'%}"></script> 4 <script src="{% static 'js/modal_poll.js'%}"></script>
5 5
6 -{% if request.user|has_role:'professor, system_admin'%}  
7 {% for poll in polls %} 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 <div class="row" id="modal_poll"> 15 <div class="row" id="modal_poll">
17 16
18 </div> 17 </div>
courses/templates/subject_category/index.html
1 {% extends 'base.html' %} 1 {% extends 'base.html' %}
2 2
3 -{% load static i18n permission_tags %} 3 +{% load static i18n permission_tags professor_access%}
4 4
5 {% block breadcrumbs %} 5 {% block breadcrumbs %}
6 6
7 <ol class="breadcrumb"> 7 <ol class="breadcrumb">
8 <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> 8 <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li>
9 -  
10 - 9 +
  10 +
11 </ol> 11 </ol>
12 {% endblock %} 12 {% endblock %}
13 13
@@ -43,12 +43,14 @@ @@ -43,12 +43,14 @@
43 <h3>{{subject}}</h3> 43 <h3>{{subject}}</h3>
44 </div> 44 </div>
45 <div class="col-md-2 col-sm-2"> 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 <a href="" class="btn">{% trans "edit" %}</a> 48 <a href="" class="btn">{% trans "edit" %}</a>
48 {% endif %} 49 {% endif %}
49 </div> 50 </div>
50 <div class="col-md-3 col-sm-3"> 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 <a href="" class="btn">{% trans "delete" %}</a> 54 <a href="" class="btn">{% trans "delete" %}</a>
53 {% endif %} 55 {% endif %}
54 </div> 56 </div>
@@ -60,6 +62,6 @@ @@ -60,6 +62,6 @@
60 </p> 62 </p>
61 </div> 63 </div>
62 </div> 64 </div>
63 - 65 +
64 66
65 {% endblock %} 67 {% endblock %}
courses/templates/topic/index.html
1 {% extends 'base.html' %} 1 {% extends 'base.html' %}
2 2
3 -{% load static i18n permission_tags %} 3 +{% load static i18n permission_tags professor_access %}
4 4
5 {% block breadcrumbs %} 5 {% block breadcrumbs %}
6 6
7 <ol class="breadcrumb"> 7 <ol class="breadcrumb">
8 <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> 8 <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li>
9 <li><a href="{% url 'course:view_subject' subject.slug %}">{{ subject }}</a></li> 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 <li class="active">{% trans 'Manage Topic' %}</li> 12 <li class="active">{% trans 'Manage Topic' %}</li>
12 {% else %} 13 {% else %}
13 <li class="active">{{ topic.name }}</li> 14 <li class="active">{{ topic.name }}</li>
@@ -54,7 +55,8 @@ @@ -54,7 +55,8 @@
54 <h3>{{subject}}</h3> 55 <h3>{{subject}}</h3>
55 </div> 56 </div>
56 <div class="col-xs-4 col-md-2 divMoreActions"> 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 <div class="btn-group"> 60 <div class="btn-group">
59 <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> 61 <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
60 <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i> 62 <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
@@ -105,7 +107,8 @@ @@ -105,7 +107,8 @@
105 <div class="col-md-4"> 107 <div class="col-md-4">
106 <i class="fa fa-file-archive-o fa-lg" aria-hidden="true">Atividade.doc</i> 108 <i class="fa fa-file-archive-o fa-lg" aria-hidden="true">Atividade.doc</i>
107 </div> 109 </div>
108 - {% if user|has_role:'professor, system_admin' %} 110 + {% professor_subject subject user as permi_test%}
  111 + {% if permi_test %}
109 <div class="col-md-4"> 112 <div class="col-md-4">
110 <label> Nota:</label> 113 <label> Nota:</label>
111 <input type="number" step="0.01"> 114 <input type="number" step="0.01">
courses/templates/topic/list_file.html 0 → 100644
@@ -0,0 +1,12 @@ @@ -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>
courses/templates/topic/list_file_edit.html 0 → 100644
@@ -0,0 +1,12 @@ @@ -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 \ No newline at end of file 13 \ No newline at end of file
courses/templatetags/list_topic_foruns.py
@@ -2,6 +2,7 @@ from django import template @@ -2,6 +2,7 @@ from django import template
2 2
3 from forum.models import Forum 3 from forum.models import Forum
4 from poll.models import Poll 4 from poll.models import Poll
  5 +from files.models import TopicFile
5 register = template.Library() 6 register = template.Library()
6 7
7 """ 8 """
@@ -28,3 +29,25 @@ def list_topic_poll(request, topic): @@ -28,3 +29,25 @@ def list_topic_poll(request, topic):
28 context['topic'] = topic 29 context['topic'] = topic
29 30
30 return context 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,7 +85,6 @@ class TopicTestCase(TestCase):
85 85
86 def test_topic_update(self): 86 def test_topic_update(self):
87 self.client.login(username='professor', password='testing') 87 self.client.login(username='professor', password='testing')
88 - print (self.subject.topics.all())  
89 url = reverse('course:update_topic',kwargs={'slug':self.subject.topics.all()[0].slug}) 88 url = reverse('course:update_topic',kwargs={'slug':self.subject.topics.all()[0].slug})
90 data = { 89 data = {
91 "name": 'new name', 90 "name": 'new name',
courses/urls.py
@@ -28,6 +28,7 @@ urlpatterns = [ @@ -28,6 +28,7 @@ urlpatterns = [
28 url(r'^forum/', include('forum.urls', namespace = 'forum')), 28 url(r'^forum/', include('forum.urls', namespace = 'forum')),
29 url(r'^poll/', include('poll.urls', namespace = 'poll')), 29 url(r'^poll/', include('poll.urls', namespace = 'poll')),
30 url(r'^exam/', include('exam.urls', namespace = 'exam')), 30 url(r'^exam/', include('exam.urls', namespace = 'exam')),
  31 + url(r'^files/', include('files.urls', namespace = 'file')),
31 url(r'^upload-material/$', views.UploadMaterialView.as_view(), name='upload_material'), 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,9 +40,9 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView):
40 else: 40 else:
41 list_courses = Course.objects.filter(students__name = self.request.user.name) 41 list_courses = Course.objects.filter(students__name = self.request.user.name)
42 categorys_courses = CourseCategory.objects.filter(course_category__students__name = self.request.user.name).distinct() 42 categorys_courses = CourseCategory.objects.filter(course_category__students__name = self.request.user.name).distinct()
43 - 43 +
44 courses_category = Course.objects.filter(category__name = self.request.GET.get('category')) 44 courses_category = Course.objects.filter(category__name = self.request.GET.get('category'))
45 - 45 +
46 none = None 46 none = None
47 q = self.request.GET.get('category', None) 47 q = self.request.GET.get('category', None)
48 if q is None: 48 if q is None:
@@ -58,7 +58,7 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView): @@ -58,7 +58,7 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView):
58 list_courses = paginator.page(1) 58 list_courses = paginator.page(1)
59 except EmptyPage: 59 except EmptyPage:
60 list_courses = paginator.page(paginator.num_pages) 60 list_courses = paginator.page(paginator.num_pages)
61 - 61 +
62 context['courses_category'] = courses_category 62 context['courses_category'] = courses_category
63 context['list_courses'] = list_courses 63 context['list_courses'] = list_courses
64 context['categorys_courses'] = categorys_courses 64 context['categorys_courses'] = categorys_courses
@@ -74,7 +74,6 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView): @@ -74,7 +74,6 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView):
74 object_list = Course.objects.filter(name__icontains = name) 74 object_list = Course.objects.filter(name__icontains = name)
75 else: 75 else:
76 object_list = Course.objects.all() 76 object_list = Course.objects.all()
77 - print(object_list)  
78 return object_list 77 return object_list
79 78
80 class CreateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edit.CreateView): 79 class CreateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edit.CreateView):
@@ -159,7 +158,6 @@ class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): @@ -159,7 +158,6 @@ class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView):
159 elif has_role(self.request.user,'professor'): 158 elif has_role(self.request.user,'professor'):
160 courses = self.request.user.courses.all() 159 courses = self.request.user.courses.all()
161 context['courses'] = courses 160 context['courses'] = courses
162 - print (courses,"jdhksjbjs")  
163 context['title'] = course.name 161 context['title'] = course.name
164 162
165 return context 163 return context
@@ -198,15 +196,15 @@ class CourseView(LoginRequiredMixin, NotificationMixin, generic.DetailView): @@ -198,15 +196,15 @@ class CourseView(LoginRequiredMixin, NotificationMixin, generic.DetailView):
198 categorys_subjects = CategorySubject.objects.filter(subject_category__professors__name = self.request.user.name).distinct() 196 categorys_subjects = CategorySubject.objects.filter(subject_category__professors__name = self.request.user.name).distinct()
199 else: 197 else:
200 categorys_subjects = CategorySubject.objects.filter(subject_category__students__name = self.request.user.name).distinct() 198 categorys_subjects = CategorySubject.objects.filter(subject_category__students__name = self.request.user.name).distinct()
201 - 199 +
202 subjects_category = Subject.objects.filter(category__name = self.request.GET.get('category')) 200 subjects_category = Subject.objects.filter(category__name = self.request.GET.get('category'))
203 - 201 +
204 none = None 202 none = None
205 q = self.request.GET.get('category', None) 203 q = self.request.GET.get('category', None)
206 if q is None: 204 if q is None:
207 none = True 205 none = True
208 context['none'] = none 206 context['none'] = none
209 - 207 +
210 context['subjects_category'] = subjects_category 208 context['subjects_category'] = subjects_category
211 context['categorys_subjects'] = categorys_subjects 209 context['categorys_subjects'] = categorys_subjects
212 context['courses'] = courses 210 context['courses'] = courses
@@ -330,14 +328,14 @@ class SubjectsView(LoginRequiredMixin, generic.ListView): @@ -330,14 +328,14 @@ class SubjectsView(LoginRequiredMixin, generic.ListView):
330 else: 328 else:
331 context['files'] = TopicFile.objects.filter(students__name = self.request.user.name) 329 context['files'] = TopicFile.objects.filter(students__name = self.request.user.name)
332 return context 330 return context
333 - 331 +
334 class UploadMaterialView(LoginRequiredMixin, generic.edit.CreateView): 332 class UploadMaterialView(LoginRequiredMixin, generic.edit.CreateView):
335 - login_url = reverse_lazy("core:home") 333 + login_url = reverse_lazy("core:home")
336 redirect_field_name = 'next' 334 redirect_field_name = 'next'
337 335
338 template_name = 'files/create_file.html' 336 template_name = 'files/create_file.html'
339 form_class = FileForm 337 form_class = FileForm
340 - 338 +
341 def form_invalid(self, form): 339 def form_invalid(self, form):
342 context = super(UploadMaterialView, self).form_invalid(form) 340 context = super(UploadMaterialView, self).form_invalid(form)
343 context.status_code = 400 341 context.status_code = 400
@@ -346,7 +344,7 @@ class UploadMaterialView(LoginRequiredMixin, generic.edit.CreateView): @@ -346,7 +344,7 @@ class UploadMaterialView(LoginRequiredMixin, generic.edit.CreateView):
346 344
347 def get_success_url(self): 345 def get_success_url(self):
348 self.success_url = reverse('course:view_subject', args = (self.object.slug, )) 346 self.success_url = reverse('course:view_subject', args = (self.object.slug, ))
349 - 347 +
350 return self.success_url 348 return self.success_url
351 349
352 class TopicsView(LoginRequiredMixin, generic.ListView): 350 class TopicsView(LoginRequiredMixin, generic.ListView):
exam/migrations/0001_initial.py
1 # -*- coding: utf-8 -*- 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 from __future__ import unicode_literals 3 from __future__ import unicode_literals
4 4
5 from django.db import migrations, models 5 from django.db import migrations, models
@@ -23,16 +23,16 @@ class Migration(migrations.Migration): @@ -23,16 +23,16 @@ class Migration(migrations.Migration):
23 ('order', models.PositiveSmallIntegerField(verbose_name='Order')), 23 ('order', models.PositiveSmallIntegerField(verbose_name='Order')),
24 ], 24 ],
25 options={ 25 options={
26 - 'ordering': ('order',),  
27 'verbose_name_plural': 'Answers', 26 'verbose_name_plural': 'Answers',
28 'verbose_name': 'Answer', 27 'verbose_name': 'Answer',
  28 + 'ordering': ('order',),
29 }, 29 },
30 ), 30 ),
31 migrations.CreateModel( 31 migrations.CreateModel(
32 name='Exam', 32 name='Exam',
33 fields=[ 33 fields=[
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')), 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 options={ 37 options={
38 'verbose_name_plural': 'Exams', 38 'verbose_name_plural': 'Exams',
exam/models.py
@@ -6,7 +6,7 @@ from core.models import Resource @@ -6,7 +6,7 @@ from core.models import Resource
6 from courses.models import Activity 6 from courses.models import Activity
7 7
8 class Exam(Activity): 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 class Meta: 11 class Meta:
12 verbose_name = _('Exam') 12 verbose_name = _('Exam')
@@ -67,7 +67,6 @@ class ViewExam(LoginRequiredMixin,generic.DetailView): @@ -67,7 +67,6 @@ class ViewExam(LoginRequiredMixin,generic.DetailView):
67 context['answers'] = answers 67 context['answers'] = answers
68 context['keys'] = keys 68 context['keys'] = keys
69 69
70 - print (context)  
71 return context 70 return context
72 71
73 72
@@ -170,7 +169,6 @@ class UpdateExam(LoginRequiredMixin,HasRoleMixin,generic.UpdateView): @@ -170,7 +169,6 @@ class UpdateExam(LoginRequiredMixin,HasRoleMixin,generic.UpdateView):
170 169
171 answers = {} 170 answers = {}
172 for answer in exam.answers.all(): 171 for answer in exam.answers.all():
173 - # print (key.answer)  
174 answers[answer.order] = answer.answer 172 answers[answer.order] = answer.answer
175 173
176 keys = sorted(answers) 174 keys = sorted(answers)
files/admin.py
1 from django.contrib import admin 1 from django.contrib import admin
2 2
3 from .models import TopicFile 3 from .models import TopicFile
4 -  
5 class TopicFileAdmin(admin.ModelAdmin): 4 class TopicFileAdmin(admin.ModelAdmin):
6 list_display = ['name', 'slug'] 5 list_display = ['name', 'slug']
7 search_fields = ['name', 'slug'] 6 search_fields = ['name', 'slug']
files/forms.py
  1 +from django.conf import settings
1 from django import forms 2 from django import forms
2 from .models import TopicFile 3 from .models import TopicFile
  4 +from django.core.exceptions import ValidationError, FieldError
3 from django.utils.translation import ugettext_lazy as _ 5 from django.utils.translation import ugettext_lazy as _
4 6
5 class FileForm(forms.ModelForm): 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 class Meta: 33 class Meta:
8 model = TopicFile 34 model = TopicFile
9 fields = ['name', 'file_url'] 35 fields = ['name', 'file_url']
10 \ No newline at end of file 36 \ No newline at end of file
files/migrations/0001_initial.py
1 # -*- coding: utf-8 -*- 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 from __future__ import unicode_literals 3 from __future__ import unicode_literals
4 4
  5 +from django.conf import settings
5 from django.db import migrations, models 6 from django.db import migrations, models
6 import django.db.models.deletion 7 import django.db.models.deletion
7 import files.models 8 import files.models
@@ -13,6 +14,7 @@ class Migration(migrations.Migration): @@ -13,6 +14,7 @@ class Migration(migrations.Migration):
13 14
14 dependencies = [ 15 dependencies = [
15 ('courses', '0001_initial'), 16 ('courses', '0001_initial'),
  17 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
16 ('core', '0001_initial'), 18 ('core', '0001_initial'),
17 ] 19 ]
18 20
@@ -23,11 +25,13 @@ class Migration(migrations.Migration): @@ -23,11 +25,13 @@ class Migration(migrations.Migration):
23 ('material_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Material')), 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 ('description', models.TextField(blank=True, verbose_name='Description')), 26 ('description', models.TextField(blank=True, verbose_name='Description')),
25 ('file_url', models.FileField(upload_to=files.models.file_path, verbose_name='File')), 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 options={ 31 options={
29 'verbose_name_plural': 'Files', 32 'verbose_name_plural': 'Files',
30 'verbose_name': 'File', 33 'verbose_name': 'File',
  34 + 'ordering': ('-id',),
31 }, 35 },
32 bases=('courses.material',), 36 bases=('courses.material',),
33 ), 37 ),
files/migrations/0002_topicfile_professor.py
@@ -1,24 +0,0 @@ @@ -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 from django.db import models 1 from django.db import models
2 from django.utils.translation import ugettext_lazy as _ 2 from django.utils.translation import ugettext_lazy as _
3 -from core.models import MymeType 3 +from core.models import MimeType
4 from courses.models import Material 4 from courses.models import Material
5 from users.models import User 5 from users.models import User
6 6
@@ -20,12 +20,13 @@ class TopicFile(Material): @@ -20,12 +20,13 @@ class TopicFile(Material):
20 professor = models.ManyToManyField(User,verbose_name=_('Professors'), related_name='file_professors') 20 professor = models.ManyToManyField(User,verbose_name=_('Professors'), related_name='file_professors')
21 description = models.TextField(_('Description'), blank=True) 21 description = models.TextField(_('Description'), blank=True)
22 file_url = models.FileField(verbose_name = _("File"), upload_to = file_path) 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 class Meta: 26 class Meta:
27 verbose_name = _("File") 27 verbose_name = _("File")
28 verbose_name_plural = _("Files") 28 verbose_name_plural = _("Files")
  29 + ordering = ('-id',)
29 30
30 def __str__(self): 31 def __str__(self):
31 return self.name 32 return self.name
32 \ No newline at end of file 33 \ No newline at end of file
files/static/css/file.css 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +.modal-backdrop{
  2 + z-index: 0;
  3 +}
0 \ No newline at end of file 4 \ No newline at end of file
files/static/js/file.js 0 → 100644
@@ -0,0 +1,63 @@ @@ -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 \ No newline at end of file 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">&times;</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">&times;</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">&times;</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 </div> 83 </div>
49 - {% endfor %}  
50 -</form>  
51 -<!-- EndModal -->  
52 \ No newline at end of file 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 \ No newline at end of file 116 \ No newline at end of file
files/templates/files/delete_file.html 0 → 100644
@@ -0,0 +1,76 @@ @@ -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">&times;</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 \ No newline at end of file 77 \ No newline at end of file
files/templates/files/render_file.html 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<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>
0 \ No newline at end of file 2 \ No newline at end of file
files/templates/files/update_file.html 0 → 100644
@@ -0,0 +1,120 @@ @@ -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">&times;</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">&times;</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 \ No newline at end of file 121 \ No newline at end of file
files/urls.py 0 → 100644
@@ -0,0 +1,11 @@ @@ -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 \ No newline at end of file 12 \ No newline at end of file
files/utils.py 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +mime_type_to_material_icons = {
  2 + 'application/pdf': 'picture_as_pdf',
  3 + 'text/plain': 'format_align_justify',
  4 + 'image/png': 'photo',
  5 + 'image/jpeg': 'photo'
  6 +}
0 \ No newline at end of file 7 \ 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 # Create your views here. 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 \ No newline at end of file 132 \ No newline at end of file
forum/migrations/0001_initial.py
1 # -*- coding: utf-8 -*- 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 from __future__ import unicode_literals 3 from __future__ import unicode_literals
4 4
  5 +from django.conf import settings
5 from django.db import migrations, models 6 from django.db import migrations, models
6 import django.db.models.deletion 7 import django.db.models.deletion
7 8
@@ -11,6 +12,7 @@ class Migration(migrations.Migration): @@ -11,6 +12,7 @@ class Migration(migrations.Migration):
11 initial = True 12 initial = True
12 13
13 dependencies = [ 14 dependencies = [
  15 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
14 ('courses', '0001_initial'), 16 ('courses', '0001_initial'),
15 ] 17 ]
16 18
@@ -24,8 +26,8 @@ class Migration(migrations.Migration): @@ -24,8 +26,8 @@ class Migration(migrations.Migration):
24 ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Create Date')), 26 ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Create Date')),
25 ], 27 ],
26 options={ 28 options={
27 - 'verbose_name_plural': 'Foruns',  
28 'verbose_name': 'Forum', 29 'verbose_name': 'Forum',
  30 + 'verbose_name_plural': 'Foruns',
29 }, 31 },
30 bases=('courses.activity',), 32 bases=('courses.activity',),
31 ), 33 ),
@@ -36,10 +38,12 @@ class Migration(migrations.Migration): @@ -36,10 +38,12 @@ class Migration(migrations.Migration):
36 ('message', models.TextField(verbose_name='Post message')), 38 ('message', models.TextField(verbose_name='Post message')),
37 ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')), 39 ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')),
38 ('post_date', models.DateTimeField(auto_now_add=True, verbose_name='Post Date')), 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 options={ 44 options={
41 - 'verbose_name_plural': 'Posts',  
42 'verbose_name': 'Post', 45 'verbose_name': 'Post',
  46 + 'verbose_name_plural': 'Posts',
43 }, 47 },
44 ), 48 ),
45 migrations.CreateModel( 49 migrations.CreateModel(
@@ -50,10 +54,11 @@ class Migration(migrations.Migration): @@ -50,10 +54,11 @@ class Migration(migrations.Migration):
50 ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')), 54 ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')),
51 ('answer_date', models.DateTimeField(auto_now_add=True, verbose_name='Answer Date')), 55 ('answer_date', models.DateTimeField(auto_now_add=True, verbose_name='Answer Date')),
52 ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Post', verbose_name='Post')), 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 options={ 59 options={
55 - 'verbose_name_plural': 'Post Answers',  
56 'verbose_name': 'Post Answer', 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,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
1 # -*- coding: utf-8 -*- 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 from __future__ import unicode_literals 3 from __future__ import unicode_literals
4 4
5 from django.db import migrations, models 5 from django.db import migrations, models
poll/migrations/0001_initial.py
1 # -*- coding: utf-8 -*- 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 from __future__ import unicode_literals 3 from __future__ import unicode_literals
4 4
  5 +from django.conf import settings
5 from django.db import migrations, models 6 from django.db import migrations, models
6 import django.db.models.deletion 7 import django.db.models.deletion
7 8
@@ -12,6 +13,7 @@ class Migration(migrations.Migration): @@ -12,6 +13,7 @@ class Migration(migrations.Migration):
12 13
13 dependencies = [ 14 dependencies = [
14 ('courses', '0001_initial'), 15 ('courses', '0001_initial'),
  16 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15 ] 17 ]
16 18
17 operations = [ 19 operations = [
@@ -23,9 +25,9 @@ class Migration(migrations.Migration): @@ -23,9 +25,9 @@ class Migration(migrations.Migration):
23 ('order', models.PositiveSmallIntegerField(verbose_name='Order')), 25 ('order', models.PositiveSmallIntegerField(verbose_name='Order')),
24 ], 26 ],
25 options={ 27 options={
26 - 'ordering': ('order',),  
27 'verbose_name_plural': 'Answers', 28 'verbose_name_plural': 'Answers',
28 'verbose_name': 'Answer', 29 'verbose_name': 'Answer',
  30 + 'ordering': ('order',),
29 }, 31 },
30 ), 32 ),
31 migrations.CreateModel( 33 migrations.CreateModel(
@@ -57,4 +59,14 @@ class Migration(migrations.Migration): @@ -57,4 +59,14 @@ class Migration(migrations.Migration):
57 name='poll', 59 name='poll',
58 field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers_stundet', to='poll.Poll', verbose_name='Poll'), 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,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
@@ -25,8 +25,7 @@ var Submite = { @@ -25,8 +25,7 @@ var Submite = {
25 $("#modal_poll").empty(); 25 $("#modal_poll").empty();
26 $("#modal_poll").append(data.responseText); 26 $("#modal_poll").append(data.responseText);
27 }); 27 });
28 - }  
29 - , 28 + },
30 remove: function(url,dados, id_li_link){ 29 remove: function(url,dados, id_li_link){
31 $('#poll').modal('hide'); 30 $('#poll').modal('hide');
32 $.post(url,dados, function(data){ 31 $.post(url,dados, function(data){
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
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -THIS FILE WAS CREATED TO TEST PURPOSES ON HEROKU.  
2 \ No newline at end of file 0 \ No newline at end of file
poll/templates/poll/view.html
@@ -30,6 +30,6 @@ @@ -30,6 +30,6 @@
30 {% block button_save %} 30 {% block button_save %}
31 <!-- Put curtom buttons here!!! --> 31 <!-- Put curtom buttons here!!! -->
32 {% if not status %} 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 {% endif %} 34 {% endif %}
35 {% endblock button_save %} 35 {% endblock button_save %}
poll/templatetags/professor_access.py 0 → 100644
@@ -0,0 +1,14 @@ @@ -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,21 +80,23 @@ class PollTestCase(TestCase):
80 self.poll.save() 80 self.poll.save()
81 81
82 def test_poll_create(self): 82 def test_poll_create(self):
83 - self.client.login(username='professor', password='testing')  
84 - poll = self.topic.activities.all().count()  
85 url = reverse('course:poll:create_poll',kwargs={'slug':self.topic.slug}) 83 url = reverse('course:poll:create_poll',kwargs={'slug':self.topic.slug})
86 data = { 84 data = {
87 "name": 'create poll test', 85 "name": 'create poll test',
88 "limit_date":'2016-10-06', 86 "limit_date":'2016-10-06',
89 "all_students":True, 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 self.client.login(username='student', password='testing') 90 self.client.login(username='student', password='testing')
94 poll = self.topic.activities.all().count() 91 poll = self.topic.activities.all().count()
95 response = self.client.post(url, data) 92 response = self.client.post(url, data)
96 self.assertEqual(poll, self.topic.activities.all().count()) # don't create a new poll 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 def test_poll_update(self): 100 def test_poll_update(self):
99 self.client.login(username='professor', password='testing') 101 self.client.login(username='professor', password='testing')
100 url = reverse('course:poll:update_poll',kwargs={'slug':self.poll.slug}) 102 url = reverse('course:poll:update_poll',kwargs={'slug':self.poll.slug})
@@ -34,7 +34,6 @@ class ViewPoll(LoginRequiredMixin,generic.DetailView): @@ -34,7 +34,6 @@ class ViewPoll(LoginRequiredMixin,generic.DetailView):
34 context['subject'] = poll.topic.subject 34 context['subject'] = poll.topic.subject
35 context['subjects'] = poll.topic.subject.course.subjects.all() 35 context['subjects'] = poll.topic.subject.course.subjects.all()
36 answered = AnswersStudent.objects.filter(poll = poll, student=self.request.user) 36 answered = AnswersStudent.objects.filter(poll = poll, student=self.request.user)
37 - print (answered)  
38 if answered.count()<1: 37 if answered.count()<1:
39 context['status'] = False 38 context['status'] = False
40 else: 39 else:
@@ -144,10 +143,8 @@ class UpdatePoll(LoginRequiredMixin,HasRoleMixin,generic.UpdateView): @@ -144,10 +143,8 @@ class UpdatePoll(LoginRequiredMixin,HasRoleMixin,generic.UpdateView):
144 context['course'] = poll.topic.subject.course 143 context['course'] = poll.topic.subject.course
145 context['subject'] = poll.topic.subject 144 context['subject'] = poll.topic.subject
146 context['subjects'] = poll.topic.subject.course.subjects.all() 145 context['subjects'] = poll.topic.subject.course.subjects.all()
147 -  
148 answers = {} 146 answers = {}
149 for answer in poll.answers.all(): 147 for answer in poll.answers.all():
150 - # print (key.answer)  
151 answers[answer.order] = answer.answer 148 answers[answer.order] = answer.answer
152 149
153 keys = sorted(answers) 150 keys = sorted(answers)
@@ -213,7 +210,6 @@ class AnswerStudentPoll(LoginRequiredMixin,generic.CreateView): @@ -213,7 +210,6 @@ class AnswerStudentPoll(LoginRequiredMixin,generic.CreateView):
213 210
214 def get_context_data(self, **kwargs): 211 def get_context_data(self, **kwargs):
215 context = super(AnswerStudentPoll, self).get_context_data(**kwargs) 212 context = super(AnswerStudentPoll, self).get_context_data(**kwargs)
216 - print (self.kwargs.get('slug'))  
217 poll = get_object_or_404(Poll, slug = self.kwargs.get('slug')) 213 poll = get_object_or_404(Poll, slug = self.kwargs.get('slug'))
218 context['poll'] = poll 214 context['poll'] = poll
219 context['topic'] = poll.topic 215 context['topic'] = poll.topic
@@ -221,7 +217,6 @@ class AnswerStudentPoll(LoginRequiredMixin,generic.CreateView): @@ -221,7 +217,6 @@ class AnswerStudentPoll(LoginRequiredMixin,generic.CreateView):
221 context['subject'] = poll.topic.subject 217 context['subject'] = poll.topic.subject
222 context['subjects'] = poll.topic.subject.course.subjects.all() 218 context['subjects'] = poll.topic.subject.course.subjects.all()
223 219
224 - print (self.request.method)  
225 answers = {} 220 answers = {}
226 for answer in poll.answers.all(): 221 for answer in poll.answers.all():
227 answers[answer.order] = answer.answer 222 answers[answer.order] = answer.answer
users/admin.py
@@ -5,6 +5,5 @@ from .forms import AdminUserForm @@ -5,6 +5,5 @@ from .forms import AdminUserForm
5 class UserAdmin(admin.ModelAdmin): 5 class UserAdmin(admin.ModelAdmin):
6 list_display = ['username', 'name', 'email', 'is_staff', 'is_active'] 6 list_display = ['username', 'name', 'email', 'is_staff', 'is_active']
7 search_fields = ['username', 'name', 'email'] 7 search_fields = ['username', 'name', 'email']
8 - form = AdminUserForm  
9 8
10 -admin.site.register(User, UserAdmin)  
11 \ No newline at end of file 9 \ No newline at end of file
  10 +admin.site.register(User, UserAdmin)