Commit c76adc40dad1568a3bada6822c075ed7538afef8

Authored by ailsoncgt
2 parents c77ab4d1 5693ed77

Merge

amadeus/settings.py
... ... @@ -185,11 +185,13 @@ MESSAGE_TAGS = {
185 185  
186 186 #Send email for forgot Password
187 187 EMAIL_USE_TLS = True
  188 +DEFAULT_FROM_EMAIL = 'test@gmail.com'
  189 +SERVER_EMAIL = 'test@gmail.com'
188 190 EMAIL_HOST = 'smtp.gmail.com'
189   -EMAIL_PORT = 25
  191 +EMAIL_PORT = 587
190 192 EMAIL_HOST_USER = 'amadeusteste@gmail.com'
191 193 EMAIL_HOST_PASSWORD = 'amadeusteste'
192   -# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
  194 +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
193 195  
194 196 #s3direct
195 197  
... ...
app/templates/home.html
... ... @@ -132,14 +132,3 @@
132 132 </center>
133 133 </div>
134 134 {% endblock %}
135   -
136   -{% block rightbar %}
137   - <div class="panel panel-warning">
138   - <div class="panel-heading">
139   - <h3 class="panel-title">Pending Stuffs</h3>
140   - </div>
141   - <div class="panel-body">
142   - <p>{% trans 'No pending tasks at the moment.' %}</p>
143   - </div>
144   - </div>
145   -{% endblock rightbar %}
146 135 \ No newline at end of file
... ...
app/templates/home_professor.html
... ... @@ -54,24 +54,3 @@
54 54 {% endif %}
55 55 {% endblock %}
56 56  
57   -{% block rightbar %}
58   - <div class="col-md-12">
59   - <div><div class="panel panel-warning">
60   - <div class="panel-heading">
61   - <h3 class="panel-title">{% trans 'Pending Stuffs' %}</h3>
62   - </div>
63   - <div class="panel-body">
64   -
65   - </div>
66   -</div></div>
67   - <div><div class="panel panel-warning">
68   - <div class="panel-heading">
69   - <h3 class="panel-title">{% trans 'Goals' %}</h3>
70   - </div>
71   - <div class="panel-body">
72   -
73   - </div>
74   -</div></div>
75   - </div>
76   -
77   -{% endblock rightbar %}
... ...
app/templates/home_student.html
... ... @@ -67,12 +67,3 @@
67 67 </div>
68 68 </div>
69 69 {% endblock %}
70   -
71   -{% block rightbar %}
72   - <div class="well well-lg goal">
73   - {% trans 'Goals' %}
74   - </div>
75   - <div class="well well-lg favorites">
76   - {% trans 'Favorites' %}
77   - </div>
78   -{% endblock rightbar %}
... ...
core/templates/base.html
... ... @@ -104,17 +104,13 @@
104 104  
105 105 {% endblock %}
106 106 <div class="row">
107   - <div class="col-xs-9 col-sm-9 col-md-9 col-lg-9 col-xl-9">
  107 + <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 col-xl-12">
108 108 {% block content %}
109 109  
110 110 {% endblock %}
111   - </div>
  111 + </div>
112 112  
113   - <div class="col-xs-3 col-sm-3 col-md-3 col-lg-3 col-xl-3">
114   - {% block rightbar %}
115   -
116   - {% endblock rightbar %}
117   - </div>
  113 +
118 114 </div>
119 115 </div>
120 116 </div>
... ...
core/templates/index.html
... ... @@ -78,6 +78,4 @@
78 78 </div>
79 79 {% endblock%}
80 80  
81   -{% block rightbar %}
82 81  
83   -{% endblock rightbar %}
... ...
courses/admin.py
1 1 from django.contrib import admin
2 2  
3   -from .models import Category, Course, Subject,Topic, Activity, Material
  3 +from .models import CourseCategory, Course, Subject,Topic, Activity, Material
4 4  
5 5 class CategoryAdmin(admin.ModelAdmin):
6 6 list_display = ['name', 'slug']
... ... @@ -26,7 +26,7 @@ class MaterialAdmin(admin.ModelAdmin):
26 26 list_display = ['name', 'slug']
27 27 search_fields = ['name', 'slug']
28 28  
29   -admin.site.register(Category, CategoryAdmin)
  29 +admin.site.register(CourseCategory, CategoryAdmin)
30 30 admin.site.register(Course, CourseAdmin)
31 31 admin.site.register(Subject, SubjectAdmin)
32 32 admin.site.register(Topic, TopicAdmin)
... ...
courses/forms.py
1 1 from django import forms
2 2 from django.utils.translation import ugettext_lazy as _
3   -from .models import Category, Course, Subject, Topic, ActivityFile, Activity
  3 +from .models import CourseCategory, Course, Subject, Topic, ActivityFile, Activity
4 4 from s3direct.widgets import S3DirectWidget
5 5  
6 6  
7   -class CategoryForm(forms.ModelForm):
  7 +class CategoryCourseForm(forms.ModelForm):
8 8  
9 9 class Meta:
10   - model = Category
  10 + model = CourseCategory
11 11 fields = ('name',)
12 12 labels = {
13 13 'name': _('Name')
14 14 }
15 15 help_texts = {
16   - 'name': _('Category name')
  16 + 'name': _('CourseCategory name')
17 17 }
18 18  
19 19  
... ... @@ -62,7 +62,7 @@ class CourseForm(forms.ModelForm):
62 62 'init_date': _('Course start date'),
63 63 'end_date': _('Course end date'),
64 64 'image': _('Image'),
65   - 'category': _('Category'),
  65 + 'category': _('CourseCategory'),
66 66 }
67 67 help_texts = {
68 68 'name': _('Course name'),
... ... @@ -74,7 +74,7 @@ class CourseForm(forms.ModelForm):
74 74 'init_date': _('Date that the course starts (dd/mm/yyyy)'),
75 75 'end_date': _('Date that the course ends (dd/mm/yyyy)'),
76 76 'image': _('Representative image of the course'),
77   - 'category': _('Category which the course belongs'),
  77 + 'category': _('CourseCategory which the course belongs'),
78 78 }
79 79  
80 80 widgets = {
... ... @@ -102,7 +102,7 @@ class UpdateCourseForm(CourseForm):
102 102 'init_date': _('Course start date'),
103 103 'end_date': _('Course end date'),
104 104 'image': _('Image'),
105   - 'category': _('Category'),
  105 + 'category': _('CourseCategory'),
106 106 'students': _('Student'),
107 107 }
108 108 help_texts = {
... ... @@ -115,7 +115,7 @@ class UpdateCourseForm(CourseForm):
115 115 'init_date': _('Date that the course starts (dd/mm/yyyy)'),
116 116 'end_date': _('Date that the course ends (dd/mm/yyyy)'),
117 117 'image': _('Representative image of the course'),
118   - 'category': _('Category which the course belongs'),
  118 + 'category': _('CourseCategory which the course belongs'),
119 119 'students': _("Course's Students"),
120 120 }
121 121 widgets = {
... ...
courses/migrations/0003_auto_20161007_1612.py 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-10-07 19:12
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.conf import settings
  6 +from django.db import migrations, models
  7 +
  8 +
  9 +class Migration(migrations.Migration):
  10 +
  11 + dependencies = [
  12 + ('courses', '0002_subject_students'),
  13 + ]
  14 +
  15 + operations = [
  16 + migrations.RenameModel(
  17 + old_name='Category',
  18 + new_name='CourseCategory',
  19 + ),
  20 + migrations.AlterField(
  21 + model_name='activity',
  22 + name='limit_date',
  23 + field=models.DateField(verbose_name='Deliver Date'),
  24 + ),
  25 + migrations.AlterField(
  26 + model_name='subject',
  27 + name='professors',
  28 + field=models.ManyToManyField(related_name='professors_subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors'),
  29 + ),
  30 + ]
... ...
courses/models.py
... ... @@ -5,7 +5,7 @@ from users.models import User
5 5 from core.models import Resource
6 6 from s3direct.fields import S3DirectField
7 7  
8   -class Category(models.Model):
  8 +class CourseCategory(models.Model):
9 9  
10 10 name = models.CharField(_('Name'), max_length = 100, unique = True)
11 11 slug = AutoSlugField(_("Slug"),populate_from='name',unique=True)
... ... @@ -31,7 +31,7 @@ class Course(models.Model):
31 31 init_date = models.DateField(_('Begin of Course Date'))
32 32 end_date = models.DateField(_('End of Course Date'))
33 33 image = models.ImageField(verbose_name = _('Image'), blank = True, upload_to = 'courses/')
34   - category = models.ForeignKey(Category, verbose_name = _('Category'))
  34 + category = models.ForeignKey(CourseCategory, verbose_name = _('Category'), related_name='course_category')
35 35 professors = models.ManyToManyField(User,verbose_name=_('Professors'), related_name='courses_professors')
36 36 students = models.ManyToManyField(User,verbose_name=_('Students'), related_name='courses_student')
37 37  
... ... @@ -91,7 +91,7 @@ Activity is something that has a deadline and has to be delivered by the student
91 91 """
92 92 class Activity(Resource):
93 93 topic = models.ForeignKey(Topic, verbose_name = _('Topic'), related_name='activities')
94   - limit_date = models.DateTimeField(_('Deliver Date'))
  94 + limit_date = models.DateField(_('Deliver Date'))
95 95 students = models.ManyToManyField(User, verbose_name = _('Students'), related_name='activities')
96 96 all_students = models.BooleanField(_('All Students'), default=False)
97 97  
... ... @@ -100,7 +100,7 @@ class ActivityFile(models.Model):
100 100 diet = models.ForeignKey('Activity', related_name='files')
101 101 name = models.CharField(max_length=100)
102 102  
103   - def __str__(self):
  103 + def __str__(self):
104 104 return self.name
105 105  
106 106 class Meta:
... ...
courses/templates/category/create.html
1 1 {% extends 'app/base.html' %}
2 2  
3   -{% load static i18n %}
  3 +{% load static i18n permission_tags %}
4 4 {% load widget_tweaks %}
5 5  
6 6 {% block breadcrumbs %}
... ... @@ -11,20 +11,37 @@
11 11 {% endblock %}
12 12  
13 13 {% block sidebar %}
14   - <div class="list-group">
15   - <a href="{% url 'course:manage_cat' %}" class="list-group-item">
16   - {% trans 'Categories' %}
17   - </a>
  14 + <div class="panel panel-primary navigation">
  15 + <div class="panel-heading">
  16 + <h5>{% trans 'Menu' %}</h5>
  17 + </div>
  18 + <div class="panel-body">
  19 + <ul class="nav nav-pills nav-stacked">
  20 + <li><a href="{% url 'users:profile' %}">{% trans 'Profile' %}</a></li>
  21 + <li><a href="{% url 'course:manage' %}">{% trans 'My Courses' %}</a></li>
  22 + </ul>
  23 + </div>
  24 + </div>
  25 +
  26 +{% if user|has_role:'professor, system_admin' %}
  27 +
  28 + <div class="panel panel-primary navigation">
  29 + <div class="panel-heading">
  30 + <h3 class="panel-title">Actions</h3>
  31 + </div>
  32 + <div class="panel-body">
  33 + <ul class="nav nav-pills nav-stacked">
  34 + <li><a href="javascript:void(0)">Replicate Course</a></li>
  35 + <li><a href="{% url 'course:create' %}">Create Course</a></li>
  36 + <li><a href="{% url 'course:create_cat' %}">Create Category</a></li>
  37 + </ul>
  38 + </div>
18 39 </div>
  40 +{% endif %}
  41 +
19 42 {% endblock %}
20 43  
21 44 {% block content %}
22   - <div class="alert alert-info alert-dismissible" role="alert">
23   - <button type="button" class="close" data-dismiss="alert" aria-label="Close">
24   - <span aria-hidden="true">&times;</span>
25   - </button>
26   - <p>{% trans 'All fields are required' %}</p>
27   - </div>
28 45  
29 46 <form method="post" action="">
30 47 {% csrf_token %}
... ...
courses/templates/course/index.html
... ... @@ -33,6 +33,7 @@
33 33 <ul class="nav nav-pills nav-stacked">
34 34 <li><a href="javascript:void(0)">Replicate Course</a></li>
35 35 <li><a href="{% url 'course:create' %}">Create Course</a></li>
  36 + <li><a href="{% url 'course:create_cat' %}">Create Category</a></li>
36 37 </ul>
37 38 </div>
38 39 </div>
... ... @@ -63,58 +64,131 @@
63 64 </span>
64 65 </div>
65 66 </div>
  67 + <div class="col-md-12">
  68 + {% if user|has_role:'professor, system_admin' %}
  69 + <div class="btn-group btn-group-justified btn-group-raised">
  70 + <a href="?category=all" class="btn btn-raised btn-info">Todos</a>
  71 + {% for category_course in categorys_courses_professor %}
  72 + <a href="?category={{category_course.name}}" class="btn btn-raised btn-primary">{{category_course.name}}</a>
  73 + {% endfor %}
  74 + </div>
  75 + {% else%}
  76 + <div class="btn-group btn-group-justified btn-group-raised">
  77 + <a href="?category=all" class="btn btn-raised btn-info">Todos</a>
  78 + {% for category_course in categorys_courses %}
  79 + <a href="?category={{category_course.name}}" class="btn btn-raised btn-primary">{{category_course.name}}</a>
  80 + {% endfor %}
  81 + </div>
  82 + {% endif %}
  83 + </div>
  84 +
  85 +</fieldset>
66 86 {% if user|has_role:'professor, system_admin' %}
67 87 <div class="col-md-12">
68 88 {% if courses|length > 0 %}
69   - {% for course in courses_teacher %}
70   - <!-- Put your content here! -->
71   - <div class="panel-group ui-accordion ui-widget ui-helper-reset ui-sortable" id="accordion" role="tablist" aria-multiselectable="false">
72   - <div class="group">
73   - <div class="panel panel-info">
74   - <div class="panel-heading" role="tab">
75   - <div class="row">
76   - <div class="col-xs-9 col-md-9 titleTopic">
77   - <a role="button" data-toggle="collapse" data-parent="#accordion" href=".collapseOne" aria-expanded="false" aria-controls="collapseOne" class="collapsed">
78   - <h4 style="color:white">{{course.name}}</h4>
79   - </a>
80   - </div>
81   - <div class="col-xs-4 col-md-3" id="divMoreActions">
82   - <div class="btn-group">
83   - <button type="button" class="btn btn-default btn-sm eye" data-toggle="tooltip" data-placement="bottom" title="Visible">
84   - <i class="fa fa-eye fa-2x" aria-hidden="true"></i>
85   - </button>
86   -
87   - </div>
88   - <div class="btn-group">
89   - <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
90   - <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
91   - </button>
92   - <ul class="dropdown-menu" aria-labelledby="moreActions">
93   - <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; Replicate</a></li>
94   - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeCourse"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp; Remove</a></li>
95   - </ul>
96   - </div>
97   - </div>
98   - </div>
99   - </div>
100   - <div class="panel-collapse collapseOne collapse in" role="tabpanel" aria-labelledby="headingOne" aria-expanded="true" aria-hidden="false" tabindex="0">
101   - <div class="panel-body">
102   - <p><b>Course Name: </b>{{course.name}}</p>
103   - <p><b>Duration (in semesters): </b>09</p>
104   - <p><b>Coordinator: </b>{{course.professors}}</p>
105   - <p>
106   - <b>Description:</b>
107   - <i>
108   - {{course.description}}
109   - </i>
110   - </p>
111   - <a href="{% url 'course:view' course.slug %}" class="btn btn-raised btn-default center-block">{% trans 'View Course' %}<div class="ripple-container"></div></a>
112   - </div>
113   - </div>
  89 + {% if request.GET.category == 'all' or none or request.GET.category == '' %}
  90 + {% for course in courses_teacher %}
  91 + <!-- Put your content here! -->
  92 + <div class="panel-group ui-accordion ui-widget ui-helper-reset ui-sortable" id="accordion" role="tablist" aria-multiselectable="false">
  93 + <div class="group">
  94 + <div class="panel panel-info">
  95 + <div class="panel-heading" role="tab">
  96 + <div class="row">
  97 + <div class="col-xs-9 col-md-9 titleTopic">
  98 + <a role="button" data-toggle="collapse" data-parent="#accordion" href=".collapseOne" aria-expanded="false" aria-controls="collapseOne" class="collapsed">
  99 + <h4 style="color:white">{{course.name}}</h4>
  100 + </a>
  101 + </div>
  102 + <div class="col-xs-4 col-md-3" id="divMoreActions">
  103 + <div class="btn-group">
  104 + <button type="button" class="btn btn-default btn-sm eye" data-toggle="tooltip" data-placement="bottom" title="Visible">
  105 + <i class="fa fa-eye fa-2x" aria-hidden="true"></i>
  106 + </button>
  107 +
  108 + </div>
  109 + <div class="btn-group">
  110 + <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
  111 + <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
  112 + </button>
  113 + <ul class="dropdown-menu" aria-labelledby="moreActions">
  114 + <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; Replicate</a></li>
  115 + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeCourse"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp; Remove</a></li>
  116 + </ul>
  117 + </div>
  118 + </div>
  119 + </div>
  120 + </div>
  121 + <div class="panel-collapse collapseOne collapse in" role="tabpanel" aria-labelledby="headingOne" aria-expanded="true" aria-hidden="false" tabindex="0">
  122 + <div class="panel-body">
  123 + <p><b>Course Name: </b>{{course.name}}</p>
  124 + <p><b>Duration (in semesters): </b>09</p>
  125 + <p><b>Coordinator: </b>{{course.professors}}</p>
  126 + <p>
  127 + <b>Description:</b>
  128 + <i>
  129 + {{course.description}}
  130 + </i>
  131 + </p>
  132 + <a href="{% url 'course:view' course.slug %}" class="btn btn-raised btn-default center-block">{% trans 'View Course' %}<div class="ripple-container"></div></a>
  133 + </div>
  134 + </div>
  135 + </div>
114 136 </div>
115 137 </div>
116   - </div>
117   - {% endfor %}
  138 + {% endfor %}
  139 + {% else %}
  140 + {% for course in courses_teacher %}
  141 + {% if course.category.name == request.GET.category %}
  142 + <!-- Put your content here! -->
  143 + <div class="panel-group ui-accordion ui-widget ui-helper-reset ui-sortable" id="accordion" role="tablist" aria-multiselectable="false">
  144 + <div class="group">
  145 + <div class="panel panel-info">
  146 + <div class="panel-heading" role="tab">
  147 + <div class="row">
  148 + <div class="col-xs-9 col-md-9 titleTopic">
  149 + <a role="button" data-toggle="collapse" data-parent="#accordion" href=".collapseOne" aria-expanded="false" aria-controls="collapseOne" class="collapsed">
  150 + <h4 style="color:white">{{course.name}}</h4>
  151 + </a>
  152 + </div>
  153 + <div class="col-xs-4 col-md-3" id="divMoreActions">
  154 + <div class="btn-group">
  155 + <button type="button" class="btn btn-default btn-sm eye" data-toggle="tooltip" data-placement="bottom" title="Visible">
  156 + <i class="fa fa-eye fa-2x" aria-hidden="true"></i>
  157 + </button>
  158 +
  159 + </div>
  160 + <div class="btn-group">
  161 + <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
  162 + <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
  163 + </button>
  164 + <ul class="dropdown-menu" aria-labelledby="moreActions">
  165 + <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; Replicate</a></li>
  166 + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeCourse"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp; Remove</a></li>
  167 + </ul>
  168 + </div>
  169 + </div>
  170 + </div>
  171 + </div>
  172 + <div class="panel-collapse collapseOne collapse in" role="tabpanel" aria-labelledby="headingOne" aria-expanded="true" aria-hidden="false" tabindex="0">
  173 + <div class="panel-body">
  174 + <p><b>Course Name: </b>{{course.name}}</p>
  175 + <p><b>Duration (in semesters): </b>09</p>
  176 + <p><b>Coordinator: </b>{{course.professors}}</p>
  177 + <p>
  178 + <b>Description:</b>
  179 + <i>
  180 + {{course.description}}
  181 + </i>
  182 + </p>
  183 + <a href="{% url 'course:view' course.slug %}" class="btn btn-raised btn-default center-block">{% trans 'View Course' %}<div class="ripple-container"></div></a>
  184 + </div>
  185 + </div>
  186 + </div>
  187 + </div>
  188 + </div>
  189 + {% endif %}
  190 + {% endfor %}
  191 + {% endif %}
118 192 {% else %}
119 193 {% trans 'No courses found' %}
120 194 {% endif %}
... ... @@ -141,55 +215,107 @@
141 215 </div>
142 216 {% else %}
143 217 {% if courses|length > 0 %}
144   - {% for course in courses_student %}
145   - <div class="col-md-12">
146   - <div class="panel panel-info">
147   - <!--{% if course.image %}
148   - <img src="{{ course.image_url }}" class="img-responsive" />
149   - {% else %}
150   - <img src="" class="img-responsive" />
151   - {% endif %} -->
152   - <div class="panel-heading">
153   - <div class="row">
154   - <div class="col-md-9">
155   - <h3 class="panel-title">{{course.name}}</h3>
156   - </div>
157   - <div class="col-md-3">
158   - <span class="label label-info">{{ course.category }}</span>
159   - <span class="label label-warning">{{ course.max_students }} {% trans 'students tops' %}</span>
160   - </div>
  218 + {% if request.GET.category == 'all' or none or request.GET.category == '' %}
  219 + {% for course in courses_student %}
  220 + <div class="col-md-12">
  221 + <div class="panel panel-info">
  222 + <!--{% if course.image %}
  223 + <img src="{{ course.image_url }}" class="img-responsive" />
  224 + {% else %}
  225 + <img src="" class="img-responsive" />
  226 + {% endif %} -->
  227 + <div class="panel-heading">
  228 + <div class="row">
  229 + <div class="col-md-9">
  230 + <h3 class="panel-title">{{course.name}}</h3>
  231 + </div>
  232 + <div class="col-md-3">
  233 + <span class="label label-info">{{ course.category }}</span>
  234 + <span class="label label-warning">{{ course.max_students }} {% trans 'students tops' %}</span>
  235 + </div>
  236 + </div>
  237 + </div>
  238 + <div class="panel-body">
  239 + <p><b>Course Name: </b>{{ course.name }}</p>
  240 + <p><b>Duration (in semesters): </b>09</p>
  241 + <p><b>Coordinator: </b>{{course.professors}}</p>
  242 + <p>
  243 + <b>Description:</b>
  244 + <i>
  245 + {% if couse.description %}
  246 + {{course.description|linebreaks}}
  247 + {% else %}
  248 + {% trans 'No description' %}
  249 + {% endif %}
  250 + </i>
  251 + </p>
  252 +
  253 + <!--{% if user|has_role:'professor, system_admin' %}
  254 + <a href="{% url 'course:update' course.slug %}" class="btn btn-sm btn-primary">
  255 + <span class="glyphicon glyphicon-edit"></span>
  256 + </a>
  257 + <a href="{% url 'course:delete' course.slug %}" class="btn btn-sm btn-danger">
  258 + <span class="glyphicon glyphicon-trash"></span>
  259 + </a>
  260 + {% endif %}-->
  261 +
  262 + <a href="{% url 'course:view' course.slug %}" class="btn btn-raised btn-default center-block">View Course</a>
161 263 </div>
162   - </div>
163   - <div class="panel-body">
164   - <p><b>Course Name: </b>{{ course.name }}</p>
165   - <p><b>Duration (in semesters): </b>09</p>
166   - <p><b>Coordinator: </b>{{course.professors}}</p>
167   - <p>
168   - <b>Description:</b>
169   - <i>
170   - {% if couse.description %}
171   - {{course.description|linebreaks}}
172   - {% else %}
173   - {% trans 'No description' %}
174   - {% endif %}
175   - </i>
176   - </p>
177   -
178   - <!--{% if user|has_role:'professor, system_admin' %}
179   - <a href="{% url 'course:update' course.slug %}" class="btn btn-sm btn-primary">
180   - <span class="glyphicon glyphicon-edit"></span>
181   - </a>
182   - <a href="{% url 'course:delete' course.slug %}" class="btn btn-sm btn-danger">
183   - <span class="glyphicon glyphicon-trash"></span>
184   - </a>
185   - {% endif %}-->
186   -
187   - <a href="{% url 'course:view' course.slug %}" class="btn btn-raised btn-default center-block">View Course</a>
188   - </div>
189   - </div>
190   - </div>
  264 + </div>
  265 + </div>
  266 + {% endfor %}
  267 + {% else %}
  268 + {% for course in courses_student %}
  269 + {% if course.category.name == request.GET.category %}
  270 + <div class="col-md-12">
  271 + <div class="panel panel-info">
  272 + <!--{% if course.image %}
  273 + <img src="{{ course.image_url }}" class="img-responsive" />
  274 + {% else %}
  275 + <img src="" class="img-responsive" />
  276 + {% endif %} -->
  277 + <div class="panel-heading">
  278 + <div class="row">
  279 + <div class="col-md-9">
  280 + <h3 class="panel-title">{{course.name}}</h3>
  281 + </div>
  282 + <div class="col-md-3">
  283 + <span class="label label-info">{{ course.category }}</span>
  284 + <span class="label label-warning">{{ course.max_students }} {% trans 'students tops' %}</span>
  285 + </div>
  286 + </div>
  287 + </div>
  288 + <div class="panel-body">
  289 + <p><b>Course Name: </b>{{ course.name }}</p>
  290 + <p><b>Duration (in semesters): </b>09</p>
  291 + <p><b>Coordinator: </b>{{course.professors}}</p>
  292 + <p>
  293 + <b>Description:</b>
  294 + <i>
  295 + {% if couse.description %}
  296 + {{course.description|linebreaks}}
  297 + {% else %}
  298 + {% trans 'No description' %}
  299 + {% endif %}
  300 + </i>
  301 + </p>
  302 +
  303 + <!--{% if user|has_role:'professor, system_admin' %}
  304 + <a href="{% url 'course:update' course.slug %}" class="btn btn-sm btn-primary">
  305 + <span class="glyphicon glyphicon-edit"></span>
  306 + </a>
  307 + <a href="{% url 'course:delete' course.slug %}" class="btn btn-sm btn-danger">
  308 + <span class="glyphicon glyphicon-trash"></span>
  309 + </a>
  310 + {% endif %}-->
191 311  
192   - {% endfor %}
  312 + <a href="{% url 'course:view' course.slug %}" class="btn btn-raised btn-default center-block">View Course</a>
  313 + </div>
  314 + </div>
  315 + </div>
  316 + {% endif %}
  317 + {% endfor %}
  318 + {% endif %}
193 319  
194 320 <nav aria-label="Page navigation">
195 321 <ul class="pagination">
... ...
courses/templates/course/update.html
... ... @@ -59,4 +59,4 @@
59 59 </br>
60 60 </br>
61 61 </br>
62   -{% endblock %}
  62 +{% endblock %}
63 63 \ No newline at end of file
... ...
courses/templates/course/view.html
... ... @@ -63,7 +63,7 @@
63 63 <ul class="dropdown-menu" aria-labelledby="moreActions">
64 64 <li><a href="javascript:void(0)" data-toggle="modal" data-target="#createSubject"><i class="fa fa-plus-square-o" aria-hidden="true"></i>&nbsp; Create Subject</a></li>
65 65 <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; Replicate</a></li>
66   - <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal3"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i>&nbsp; Edit</a></li>
  66 + <li><a href="{% url 'course:update' course.slug %}"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i>&nbsp; Edit</a></li>
67 67 <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal2"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp; Remove</a></li>
68 68 </ul>
69 69 </div>
... ... @@ -248,20 +248,11 @@
248 248 </div>
249 249 </div>
250 250 </div>
  251 +
  252 +
251 253 </div>
252 254 </div>
253 255 </div>
254 256  
255 257 {% endblock %}
256 258  
257   -
258   -{% block rightbar %}
259   -<div class="panel panel-warning">
260   - <div class="panel-heading">
261   - <h3 class="panel-title">{% trans "Pending Stuffs" %}</h3>
262   - </div>
263   - <div class="panel-body">
264   - <p>{% trans 'No pending tasks at the moment.' %}</p>
265   - </div>
266   - </div>
267   -{% endblock rightbar %}
... ...
courses/templates/subject/index.html
... ... @@ -61,11 +61,21 @@
61 61 </div>
62 62 </div>
63 63 <div class="panel-body">
64   - <p>
65   - {{subject.description|linebreaks}}
66   - </p>
67   - </div>
68   - </div>
  64 + <p><b>Professor:</b> {{subject.professors}}</p>
  65 + <p>
  66 + <b>Description:</b>
  67 + {{subject.description|linebreaks}}
  68 + </p>
  69 + <div class="row">
  70 + <div class="col-xs-6 col-md-6">
  71 + <p><b>Begining:</b> {{subject.init_date}}</p>
  72 + </div>
  73 + <div class="col-xs-6 col-md-6">
  74 + <p><b>End:</b> {{subject.end_date}}</p>
  75 + </div>
  76 + </div>
  77 + </div>
  78 + </div>
69 79  
70 80 {% for topic in topics %}
71 81 {% if user|has_role:'system_admin' or topic.owner == user%}
... ... @@ -82,15 +92,3 @@
82 92 {% endif %}
83 93  
84 94 {% endblock %}
85   -
86   -{% block rightbar %}
87   -
88   - <div class="panel panel-warning">
89   - <div class="panel-heading">
90   - <h3 class="panel-title">{% trans "Pending Stuffs" %}</h3>
91   - </div>
92   - <div class="panel-body">
93   -
94   - </div>
95   - </div>
96   -{% endblock rightbar %}
... ...
courses/templates/subject_category/index.html
... ... @@ -63,15 +63,3 @@
63 63  
64 64  
65 65 {% endblock %}
66   -
67   -{% block rightbar %}
68   -
69   - <div class="panel panel-warning">
70   - <div class="panel-heading">
71   - <h3 class="panel-title">{% trans "Pending Stuffs" %}</h3>
72   - </div>
73   - <div class="panel-body">
74   -
75   - </div>
76   - </div>
77   -{% endblock rightbar %}
78 66 \ No newline at end of file
... ...
courses/templates/topic/index.html
... ... @@ -149,15 +149,3 @@
149 149 </div>
150 150 </div>
151 151 {% endblock %}
152   -
153   -{% block rightbar %}
154   -
155   - <div class="panel panel-warning">
156   - <div class="panel-heading">
157   - <h3 class="panel-title">{% trans "Pending Stuffs" %}</h3>
158   - </div>
159   - <div class="panel-body">
160   -
161   - </div>
162   - </div>
163   -{% endblock rightbar %}
... ...
courses/views.py
... ... @@ -11,8 +11,8 @@ from rolepermissions.verifications import has_role
11 11 from django.db.models import Q
12 12 from rolepermissions.verifications import has_object_permission
13 13  
14   -from .forms import CourseForm, UpdateCourseForm, CategoryForm, SubjectForm,TopicForm,ActivityForm
15   -from .models import Course, Subject, Category,Topic, SubjectCategory,Activity
  14 +from .forms import CourseForm, UpdateCourseForm, CategoryCourseForm, SubjectForm,TopicForm,ActivityForm
  15 +from .models import Course, Subject, CourseCategory,Topic, SubjectCategory,Activity
16 16 from core.mixins import NotificationMixin
17 17 from users.models import User
18 18  
... ... @@ -29,9 +29,18 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView):
29 29  
30 30 def get_context_data(self, **kwargs):
31 31 context = super(IndexView, self).get_context_data(**kwargs)
32   - context['categories'] = Category.objects.all()
  32 + context['categories'] = CourseCategory.objects.all()
33 33 context['courses_teacher'] = Course.objects.filter(professors__name = self.request.user.name)
34 34 context['courses_student'] = Course.objects.filter(students__name = self.request.user.name)
  35 + context['categorys_courses'] = CourseCategory.objects.filter(course_category__students__name = self.request.user.name).distinct()
  36 + context['categorys_courses_professor'] = CourseCategory.objects.filter(course_category__professors__name = self.request.user.name).distinct()
  37 + courses_category = Course.objects.filter(category__name = self.request.GET.get('category'))
  38 + context['courses_category'] = courses_category
  39 + none = None
  40 + q = self.request.GET.get('category', None)
  41 + if q is None:
  42 + none = True
  43 + context['none'] = none
35 44  
36 45 return context
37 46  
... ... @@ -178,13 +187,13 @@ class FilteredView(LoginRequiredMixin, generic.ListView):
178 187 paginate_by = 3
179 188  
180 189 def get_queryset(self):
181   - category = get_object_or_404(Category, slug = self.kwargs.get('slug'))
  190 + category = get_object_or_404(CourseCategory, slug = self.kwargs.get('slug'))
182 191 return Course.objects.filter(category = category)
183 192  
184 193 def get_context_data(self, **kwargs):
185   - category = get_object_or_404(Category, slug = self.kwargs.get('slug'))
  194 + category = get_object_or_404(CourseCategory, slug = self.kwargs.get('slug'))
186 195 context = super(FilteredView, self).get_context_data(**kwargs)
187   - context['categories'] = Category.objects.all()
  196 + context['categories'] = CourseCategory.objects.all()
188 197 context['cat'] = category
189 198  
190 199 return context
... ... @@ -193,10 +202,9 @@ class IndexCatView(LoginRequiredMixin, generic.ListView):
193 202  
194 203 login_url = reverse_lazy("core:home")
195 204 redirect_field_name = 'next'
196   - queryset = Category.objects.all()
  205 + queryset = CourseCategory.objects.all()
197 206 template_name = 'category/index.html'
198 207 context_object_name = 'categories'
199   - paginate_by = 3
200 208  
201 209 class CreateCatView(LoginRequiredMixin, HasRoleMixin, generic.edit.CreateView):
202 210  
... ... @@ -204,33 +212,23 @@ class CreateCatView(LoginRequiredMixin, HasRoleMixin, generic.edit.CreateView):
204 212 login_url = reverse_lazy("core:home")
205 213 redirect_field_name = 'next'
206 214 template_name = 'category/create.html'
207   - form_class = CategoryForm
  215 + form_class = CategoryCourseForm
208 216 success_url = reverse_lazy('course:manage_cat')
209 217  
210   - def render_to_response(self, context, **response_kwargs):
211   - messages.success(self.request, _('Category created successfully!'))
212   -
213   - return self.response_class(request=self.request, template=self.get_template_names(), context=context, using=self.template_engine)
214   -
215 218 class UpdateCatView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView):
216 219  
217 220 allowed_roles = ['professor', 'system_admin']
218 221 login_url = reverse_lazy("core:home")
219 222 redirect_field_name = 'next'
220 223 template_name = 'category/update.html'
221   - model = Category
222   - form_class = CategoryForm
  224 + model = CourseCategory
  225 + form_class = CategoryCourseForm
223 226 success_url = reverse_lazy('course:manage_cat')
224 227  
225   - def render_to_response(self, context, **response_kwargs):
226   - messages.success(self.request, _('Category edited successfully!'))
227   -
228   - return self.response_class(request=self.request, template=self.get_template_names(), context=context, using=self.template_engine)
229   -
230 228 class ViewCat(LoginRequiredMixin, generic.DetailView):
231 229 login_url = reverse_lazy("core:home")
232 230 redirect_field_name = 'next'
233   - model = Category
  231 + model = CourseCategory
234 232 template_name = 'category/view.html'
235 233 context_object_name = 'category'
236 234  
... ... @@ -239,7 +237,7 @@ class DeleteCatView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView):
239 237 allowed_roles = ['professor', 'system_admin']
240 238 login_url = reverse_lazy("core:home")
241 239 redirect_field_name = 'next'
242   - model = Category
  240 + model = CourseCategory
243 241 template_name = 'category/delete.html'
244 242 success_url = reverse_lazy('course:manage_cat')
245 243  
... ...
forum/templates/forum/forum_view.html
... ... @@ -124,13 +124,3 @@
124 124 </div>
125 125 {% endblock %}
126 126  
127   -{% block rightbar %}
128   - <div class="panel panel-warning">
129   - <div class="panel-heading">
130   - <h3 class="panel-title">{% trans "Pending Stuffs" %}</h3>
131   - </div>
132   - <div class="panel-body">
133   -
134   - </div>
135   - </div>
136   -{% endblock rightbar %}
... ...
forum/tests/test_model_answer.py
... ... @@ -2,7 +2,7 @@ from django.test import TestCase
2 2 from rolepermissions.shortcuts import assign_role
3 3  
4 4 from users.models import User
5   -from courses.models import Category, Course, Subject, Topic
  5 +from courses.models import CourseCategory, Course, Subject, Topic
6 6 from forum.models import Forum, Post, PostAnswer
7 7  
8 8 class PostAnswerTestCase (TestCase):
... ... @@ -28,9 +28,9 @@ class PostAnswerTestCase (TestCase):
28 28 )
29 29 assign_role(self.user_student, 'student')
30 30  
31   - self.category = Category.objects.create(
  31 + self.category = CourseCategory.objects.create(
32 32 name = 'Categoria Teste',
33   - slug = 'categoria_teste'
  33 + create_date='2016-10-07',
34 34 )
35 35 self.category.save()
36 36  
... ...
forum/tests/test_model_forum.py
... ... @@ -3,7 +3,7 @@ from django.core.urlresolvers import reverse
3 3 from rolepermissions.shortcuts import assign_role
4 4  
5 5 from users.models import User
6   -from courses.models import Category, Course, Subject, Topic
  6 +from courses.models import CourseCategory, Course, Subject, Topic
7 7 from forum.models import Forum
8 8  
9 9 class ForumTestCase (TestCase):
... ... @@ -29,9 +29,9 @@ class ForumTestCase (TestCase):
29 29 )
30 30 assign_role(self.user_student, 'student')
31 31  
32   - self.category = Category.objects.create(
  32 + self.category = CourseCategory.objects.create(
33 33 name = 'Categoria Teste',
34   - slug = 'categoria_teste'
  34 + create_date='2016-10-07',
35 35 )
36 36 self.category.save()
37 37  
... ...
forum/tests/test_model_post.py
... ... @@ -2,7 +2,7 @@ from django.test import TestCase
2 2 from rolepermissions.shortcuts import assign_role
3 3  
4 4 from users.models import User
5   -from courses.models import Category, Course, Subject, Topic
  5 +from courses.models import CourseCategory, Course, Subject, Topic
6 6 from forum.models import Forum, Post
7 7  
8 8 class PostTestCase (TestCase):
... ... @@ -28,9 +28,9 @@ class PostTestCase (TestCase):
28 28 )
29 29 assign_role(self.user_student, 'student')
30 30  
31   - self.category = Category.objects.create(
  31 + self.category = CourseCategory.objects.create(
32 32 name = 'Categoria Teste',
33   - slug = 'categoria_teste'
  33 + create_date='2016-10-07',
34 34 )
35 35 self.category.save()
36 36  
... ...
links/admin.py
1 1 from django.contrib import admin
2 2  
3   -# Register your models here.
  3 +from .models import Link
  4 +
  5 +class LinkAdmin(admin.ModelAdmin):
  6 + list_display = ['name', 'link','description']
  7 + search_fields = ['name', 'link','description']
  8 +
  9 +
  10 +admin.site.register(Link, LinkAdmin)
... ...
links/forms.py
1 1 from django import forms
2 2 from .models import Link
  3 +import validators
3 4  
4 5 class CreateLinkForm(forms.ModelForm):
  6 + def validate_link(self,link):
  7 + if not validators.url(link):
  8 + raise forms.ValidationError(_('Please enter a valid URL'))
  9 + else:
  10 + return link
  11 +
5 12 class Meta:
6 13 model = Link
7 14 fields = ['name','link','description']
8   -
  15 +
9 16 class UpdateLinkForm(forms.ModelForm):
10 17 class Meta:
11 18 model = Link
... ...
links/tests.py
1   -from django.test import TestCase
  1 +from django.test import TestCase,Client
  2 +from django.core.urlresolvers import reverse
  3 +from rolepermissions.shortcuts import assign_role
  4 +
  5 +from users.models import User
  6 +from .models import *
2 7  
3 8 # Create your tests here.
  9 +class LinkTestCase(TestCase):
  10 + def setUp(self):
  11 + self.client = Client()
  12 + self.user = User.objects.create_user(
  13 + username = 'test',
  14 + email = 'testing@amadeus.com',
  15 + is_staff = True,
  16 + is_active = True,
  17 + password = 'testing'
  18 + )
  19 + assign_role(self.user, 'system_admin')
  20 + def test_create_link(self):
  21 + self.client.login(username='user', password = 'testing')
  22 + links = Link.objects.all().count()
  23 + self.assertEqual(Link.objects.all().count(),links) #Before creating the link
  24 + self.link = Link.objects.create(
  25 + name = 'testinglink',
  26 + description = 'testdescription',
  27 + link = 'teste.com'
  28 + )
  29 + self.assertEqual(Link.objects.all().count(),links+1) #After creating one link, if OK, the link was created successfully.
  30 + # def test_update_link():
  31 + # pass
  32 + # def test_delete_link():
  33 + # pass
... ...
links/urls.py 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +from django.conf.urls import url, include
  2 +from . import views
  3 +
  4 +urlpatterns = [
  5 + url(r'^$', views.CreateLink.as_view(), name='teste')
  6 +]
... ...
links/views.py
... ... @@ -10,23 +10,29 @@ from .forms import *
10 10  
11 11 # Create your views here.
12 12 class CreateLink(generic.CreateView):
13   - template_name = 'links/'
  13 + template_name = 'links/link_modal.html'
14 14 form_class = CreateLinkForm
15 15 success_url = reverse_lazy()
  16 + context_object_name = 'links'
  17 +
16 18 def form_valid(self, form):
17   - form.save()
18   - messages.success(self.request, _('Link created successfully!'))
19   - return super(CreateLink, self).form_valid(form)
  19 + form.save()
  20 + messages.success(self.request, _('Link created successfully!'))
  21 + return super(CreateLink, self).form_valid(form)
  22 + def get_context_data(self, **kwargs):
  23 + context = {}
  24 + context['links'] = Link.objects.all()
  25 + return context
20 26  
21 27  
22 28 class DeleteLink(generic.DeleteView):
23   -
  29 + pass
24 30 class UpdateLink(generic.UpdateView):
25 31 template_name = 'links/'
26 32 form_class = UpdateLinkForm
27 33 success_url = reverse_lazy()
28 34 def form_valid(self, form):
29   - form.save()
30   - messages.success(self.request, _('Link updated successfully!'))
  35 + form.save()
  36 + messages.success(self.request, _('Link updated successfully!'))
31 37  
32   - return super(UpdateLink, self).form_valid(form)
  38 + return super(UpdateLink, self).form_valid(form)
... ...
poll/permissions.py
... ... @@ -10,3 +10,13 @@ def edit_poll(role, user, poll):
10 10 return True
11 11  
12 12 return False
  13 +
  14 +@register_object_checker()
  15 +def delete_poll(role, user, poll):
  16 + if (role == SystemAdmin):
  17 + return True
  18 +
  19 + if (user in poll.topic.subject.professors.all()):
  20 + return True
  21 +
  22 + return False
... ...
poll/templates/poll/view.html
1   -{% extends "topic/index.html" %}
  1 +{% extends "poll/create.html" %}
2 2  
3   -{% load i18n widget_tweaks dict_access static%}
4   -{% block content %}
5   -<!-- Modal (remember to change the ids!!!) -->
6   -<div class="modal fade" id="poll" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
7   - <div class="modal-dialog" role="document">
8   - <div class="modal-content">
  3 +{% load i18n dict_access static%}
9 4  
10   - <!-- Modal Header -->
11   - <div class="modal-header">
  5 +{% block style %}
  6 +{% endblock %}
12 7  
13   - <!-- Put your title here!!! -->
14   - <h4 class="modal-title" id="myModalLabel">{{form.question}}</h4>
  8 +{% block title_poll %}
  9 +<!-- Put your title here!!! -->
  10 +<h4 class="modal-title" id="myModalLabel">{{poll}}</h4>
  11 +{% endblock title_poll %}
15 12  
16   - </div>
17   - <!-- Modal Body -->
18   - <div class="modal-body">
19   -
20   - <!-- Put ONLY your content here!!! -->
21   - <div class="conteiner">
22   - </div>
23   - <form id="form" method="post">
24   - {% csrf_token %}
25   - {% for key in keys %}
26   - <div class="row form-group">
27   - <div class="col-md-1">
28   - </br>
29   - <label><span class="glyphicon glyphicon-move"></span></label>
30   - </div>
31   - <div class="col-md-10">
32   - <div class="has-success is-empty">
33   - <input type="text" name="{{key}}" class="form-control" placeholder='{% trans "Answer" %}' value="{{ answers|value:key }}">
34   - <span class="help-block">{% trans "Possible answer for the question" %}</span>
35   - </div>
36   - </div>
37   - <div class="col-md-1">
38   - </br>
39   - <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label>
40   - </div>
41   - </div>
42   - {% empty %}
43   - <div class="row form-group">
44   - <div class="col-md-1">
45   - </br>
46   - <label><span class="glyphicon glyphicon-move"></span></label>
47   - </div>
48   - <div class="col-md-10">
49   - <div class="has-success is-empty">
50   - <input type="text" name="1" class="form-control" placeholder='{% trans "Answer" %}'>
51   - <span class="help-block">{% trans "Possible answer for the question" %}</span>
52   - </div>
53   - </div>
54   - <div class="col-md-1">
55   - </br>
56   - <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label>
57   - </div>
58   - </div>
59   - {% endfor %}
60   - </form>
61   - </br>
62   - </div>
63   - <button type="button" id="add" class="btn btn-primary btn-block btn-sm">add</button>
64   - <div class="row form-group">
65   - <input form="form" class="form-control" type="date" name="{{form.limit_date.name}}" {% if form.limit_date.value != None %}value="{% if form.limit_date.value.year %}{{form.limit_date.value|date:'Y-m-d'}}{% else %}{{form.limit_date.value}}{% endif %}"{% endif %}>
66   - {% if form.limit_date.errors %}
67   - <div class="not_submited">
68   - </br>
69   - <div class="alert alert-danger alert-dismissible" role="alert">
70   - <button type="button" class="close" data-dismiss="alert" aria-label="Close">
71   - <span aria-hidden="true">&times;</span>
72   - </button>
73   - <ul>
74   - {% for error in form.limit_date.errors %}
75   - <li>{{ error }}</li>
76   - {% endfor %}
77   - </ul>
78   - </div>
79   - </div>
80   - {% endif %}
81   - </div>
82   -
83   - </div>
84   -
85   - <!-- Modal Footer -->
86   - <div class="modal-footer">
87   -
88   - <!-- Don't remove that!!! -->
89   - <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
90   -
91   - <!-- Put curtom buttons here!!! -->
92   - <button type="submite" id="button" form="form" class="btn btn-primary btn-raised">{% trans "Create" %}</button>
93   - </div>
94   -
95   - </div>
  13 +{% block content_poll %}
  14 +<!-- Put ONLY your content here!!! -->
  15 +<div class="row">
  16 + <div class="col-md-10 col-md-offset-1">
  17 + <h3>{% trans "Limit date:" %} {{poll.limit_date|date:'d/m/y'}}</h3>
96 18 </div>
97 19 </div>
98   -<a href="" data-toggle="modal" data-target="#poll">modal</a>
99   -{% endblock content %}
  20 +{% endblock content_poll %}
  21 +
  22 +{% block button_save %}
  23 +<!-- Put curtom buttons here!!! -->
  24 +<button type="submite" id="button" form="form" class="btn btn-primary btn-raised">{% trans "Answer" %}</button>
  25 +{% endblock button_save %}
... ...
poll/tests/__init__.py 0 → 100644
poll/tests/poll.py 0 → 100644
... ... @@ -0,0 +1,131 @@
  1 +# coding=utf-8
  2 +
  3 +from django.test import TestCase, Client
  4 +from django.core.urlresolvers import reverse
  5 +
  6 +from rolepermissions.shortcuts import assign_role
  7 +
  8 +from courses.models import Category, Course, Subject, Topic
  9 +from poll.models import Poll
  10 +from users.models import User
  11 +
  12 +class PollTestCase(TestCase):
  13 + def setUp(self):
  14 + self.client = Client()
  15 +
  16 + self.user_professor = User.objects.create_user(
  17 + username = 'professor',
  18 + email = 'professor@amadeus.com',
  19 + is_staff = False,
  20 + is_active = True,
  21 + password = 'testing',
  22 + type_profile = 1
  23 + )
  24 + assign_role(self.user_professor, 'professor')
  25 +
  26 + self.user_student = User.objects.create_user(
  27 + username = 'student',
  28 + email = 'student@amadeus.com',
  29 + is_staff = False,
  30 + is_active = True,
  31 + password = 'testing',
  32 + type_profile = 2
  33 + )
  34 + assign_role(self.user_student, 'student')
  35 +
  36 + self.category = Category(
  37 + name = 'Categoria Teste',
  38 + )
  39 + self.category.save()
  40 +
  41 + self.course = Course(
  42 + name = 'Curso Teste',
  43 + max_students = 50,
  44 + objectivies = "",
  45 + content = "",
  46 + init_register_date = '2016-08-26',
  47 + end_register_date = '2016-10-01',
  48 + init_date = '2016-10-05',
  49 + end_date = '2017-10-05',
  50 + category = self.category
  51 + )
  52 + self.course.save()
  53 +
  54 + self.subject = Subject(
  55 + name = 'Subject Test',
  56 + description = "description of the subject test",
  57 + visible = True,
  58 + course = self.course,
  59 + init_date = '2016-10-05',
  60 + end_date = '2017-10-05',
  61 + )
  62 + self.subject.save()
  63 +
  64 + self.subject.professors.add(self.user_professor)
  65 +
  66 + self.topic = Topic(
  67 + name = 'Topic Test',
  68 + description = "description of the topic test",
  69 + subject = self.subject,
  70 + owner = self.user_professor,
  71 + visible = True,
  72 + )
  73 + self.topic.save()
  74 +
  75 + self.poll = Poll(
  76 + name = 'Poll Test',
  77 + limit_date = '2016-10-05',
  78 + topic = self.topic,
  79 + )
  80 + self.poll.save()
  81 +
  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})
  86 + data = {
  87 + "name": 'create poll test',
  88 + "limit_date":'2016-10-06',
  89 + "all_students":True,
  90 + }
  91 + response = self.client.post(url, data)
  92 + self.assertEqual(poll + 1, self.topic.activities.all().count()) # create a new poll
  93 + self.client.login(username='student', password='testing')
  94 + poll = self.topic.activities.all().count()
  95 + response = self.client.post(url, data)
  96 + self.assertEqual(poll, self.topic.activities.all().count()) # don't create a new poll
  97 +
  98 + def test_poll_update(self):
  99 + self.client.login(username='professor', password='testing')
  100 + url = reverse('course:poll:update_poll',kwargs={'slug':self.poll.slug})
  101 + title_poll = 'new poll name'
  102 + data = {
  103 + "name": title_poll,
  104 + "limit_date":'2016-11-06',
  105 + "all_students":True,
  106 + }
  107 + self.assertNotEqual(title_poll, self.topic.activities.all()[self.topic.activities.all().count() - 1].name) # old name
  108 + response = self.client.post(url, data)
  109 + self.assertEqual(title_poll,self.topic.activities.all()[self.topic.activities.all().count() - 1].name) # new name
  110 + poll_student = 'new poll name student'
  111 + data = {
  112 + "name": poll_student,
  113 + "limit_date":'2016-11-06',
  114 + "all_students":True,
  115 + }
  116 + self.client.login(username='student', password='testing')
  117 + self.assertNotEqual(poll_student, self.topic.activities.all()[self.topic.activities.all().count() - 1].name) # old name
  118 + response = self.client.post(url, data)
  119 + self.assertNotEqual(poll_student, self.topic.activities.all()[self.topic.activities.all().count() - 1].name) # new name
  120 +
  121 + def test_poll_delete(self):
  122 + url = reverse('course:poll:delete_poll',kwargs={'slug':self.poll.slug})
  123 + self.client.login(username='student', password='testing')
  124 + poll = self.topic.activities.all().count()
  125 + response = self.client.post(url)
  126 + self.assertEqual(poll,self.topic.activities.all().count())
  127 +
  128 + self.client.login(username='professor', password='testing')
  129 + poll = self.topic.activities.all().count()
  130 + response = self.client.post(url)
  131 + self.assertEqual(poll - 1,self.topic.activities.all().count())
... ...
poll/urls.py
... ... @@ -3,10 +3,9 @@ from django.conf.urls import url
3 3 from . import views
4 4  
5 5 urlpatterns = [
  6 + url(r'^view/(?P<slug>[\w\-_]+)/$', views.ViewPoll.as_view(), name='view_poll'), # poll slug
6 7 url(r'^create/(?P<slug>[\w\-_]+)/$', views.CreatePoll.as_view(), name='create_poll'), # topic slug
7 8 url(r'^update/(?P<slug>[\w\-_]+)/$', views.UpdatePoll.as_view(), name='update_poll'), # poll slug
8   - url(r'^teste/(?P<slug>[\w\-_]+)/$', views.CreatePollModal.as_view(), name='teste'), # poll
9   - url(r'^mymodal/', views.MyModal.as_view(), name='mymodal'),
10 9 url(r'^delete/(?P<slug>[\w\-_]+)/$', views.DeletePoll.as_view(), name='delete_poll'), # poll
11 10  
12 11 ]
... ...
poll/views.py
... ... @@ -17,8 +17,63 @@ from core.mixins import NotificationMixin
17 17 from users.models import User
18 18 from courses.models import Course, Topic
19 19  
20   -class CreatePoll(LoginRequiredMixin,generic.CreateView):
  20 +class ViewPoll(LoginRequiredMixin,generic.DetailView):
21 21  
  22 + model = Poll
  23 + context_object_name = 'poll'
  24 + template_name = 'poll/view.html'
  25 +
  26 + def get_object(self, queryset=None):
  27 + return get_object_or_404(Poll, slug = self.kwargs.get('slug'))
  28 +
  29 + def form_invalid(self, form,**kwargs):
  30 + context = super(ViewPoll, self).form_invalid(form)
  31 + answers = {}
  32 + for key in self.request.POST:
  33 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'limit_date' and key != 'all_students' and key != 'students'):
  34 + answers[key] = self.request.POST[key]
  35 +
  36 + keys = sorted(answers)
  37 + context.context_data['answers'] = answers
  38 + context.context_data['keys'] = keys
  39 + return context
  40 +
  41 + def form_valid(self, form):
  42 + poll = self.object
  43 + poll = form.save(commit = False)
  44 + poll.answers.all().delete()
  45 + poll.save()
  46 +
  47 +
  48 + for key in self.request.POST:
  49 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'limit_date' and key != 'all_students' and key != 'students'):
  50 + answer = Answer(answer=self.request.POST[key],order=key,poll=poll)
  51 + answer.save()
  52 +
  53 + return super(ViewPoll, self).form_valid(form)
  54 +
  55 + def get_context_data(self, **kwargs):
  56 + context = super(ViewPoll, self).get_context_data(**kwargs)
  57 + poll = self.object
  58 + context['course'] = poll.topic.subject.course
  59 + context['subject'] = poll.topic.subject
  60 + context['subjects'] = poll.topic.subject.course.subjects.all()
  61 +
  62 + answers = {}
  63 + for answer in poll.answers.all():
  64 + answers[answer.order] = answer.answer
  65 +
  66 + keys = sorted(answers)
  67 + context['answers'] = answers
  68 + context['keys'] = keys
  69 +
  70 + print (context)
  71 + return context
  72 +
  73 +
  74 +class CreatePoll(LoginRequiredMixin,HasRoleMixin,generic.CreateView):
  75 +
  76 + allowed_roles = ['professor', 'system_admin']
22 77 login_url = reverse_lazy("core:home")
23 78 redirect_field_name = 'next'
24 79 model = Poll
... ... @@ -60,8 +115,9 @@ class CreatePoll(LoginRequiredMixin,generic.CreateView):
60 115 context['subjects'] = topic.subject.course.subjects.all()
61 116 return context
62 117  
63   -class UpdatePoll(LoginRequiredMixin,generic.UpdateView):
  118 +class UpdatePoll(LoginRequiredMixin,HasRoleMixin,generic.UpdateView):
64 119  
  120 + allowed_roles = ['professor', 'system_admin']
65 121 login_url = reverse_lazy("core:home")
66 122 redirect_field_name = 'next'
67 123 model = Poll
... ... @@ -123,7 +179,7 @@ class UpdatePoll(LoginRequiredMixin,generic.UpdateView):
123 179  
124 180 return context
125 181  
126   -class DeletePoll(LoginRequiredMixin, generic.DeleteView):
  182 +class DeletePoll(LoginRequiredMixin, HasRoleMixin, generic.DeleteView):
127 183  
128 184 allowed_roles = ['professor', 'system_admin']
129 185 login_url = reverse_lazy("core:home")
... ... @@ -131,11 +187,11 @@ class DeletePoll(LoginRequiredMixin, generic.DeleteView):
131 187 model = Poll
132 188 template_name = 'poll/remove.html'
133 189  
134   - # def dispatch(self, *args, **kwargs):
135   - # poll = get_object_or_404(Poll, slug = self.kwargs.get('slug'))
136   - # if(not has_object_permission('delete_subject', self.request.user, subject)):
137   - # return self.handle_no_permission()
138   - # return super(DeleteSubjectView, self).dispatch(*args, **kwargs)
  190 + def dispatch(self, *args, **kwargs):
  191 + poll = get_object_or_404(Poll, slug = self.kwargs.get('slug'))
  192 + if(not has_object_permission('delete_poll', self.request.user, poll)):
  193 + return self.handle_no_permission()
  194 + return super(DeletePoll, self).dispatch(*args, **kwargs)
139 195  
140 196  
141 197 def get_context_data(self, **kwargs):
... ... @@ -150,70 +206,3 @@ class DeletePoll(LoginRequiredMixin, generic.DeleteView):
150 206  
151 207 def get_success_url(self):
152 208 return reverse_lazy('course:view_topic', kwargs={'slug' : self.object.topic.slug})
153   -
154   -
155   -from django_modalview.generic.edit import ModalCreateView
156   -from django_modalview.generic.component import ModalResponse
157   -
158   -class CreatePollModal(LoginRequiredMixin,ModalCreateView):
159   -
160   - login_url = reverse_lazy("core:home")
161   - redirect_field_name = 'next'
162   - model = Poll
163   - form_class = PollForm
164   - context_object_name = 'poll'
165   - template_name = 'poll/create.html'
166   - success_url = reverse_lazy('core:home')
167   -
168   - def form_invalid(self, form,**kwargs):
169   - context = super(CreatePollModal, self).form_invalid(form)
170   - answers = {}
171   - for key in self.request.POST:
172   - if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'limit_date' and key != 'all_students' and key != 'students'):
173   - answers[key] = self.request.POST[key]
174   -
175   - keys = sorted(answers)
176   - context.context_data['answers'] = answers
177   - context.context_data['keys'] = keys
178   - return context
179   -
180   - def form_valid(self, form):
181   - self.object = form.save(commit = False)
182   - topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
183   - self.object.topic = topic
184   - self.object.save()
185   -
186   - for key in self.request.POST:
187   - if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'limit_date' and key != 'all_students' and key != 'students'):
188   - answer = Answer(answer=self.request.POST[key],order=key,poll=self.object)
189   - answer.save()
190   -
191   - return super(CreatePollModal, self).form_valid(form)
192   -
193   - def get_context_data(self, **kwargs):
194   - context = super(CreatePollModal, self).get_context_data(**kwargs)
195   - topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
196   - context['course'] = topic.subject.course
197   - context['subject'] = topic.subject
198   - context['subjects'] = topic.subject.course.subjects.all()
199   - return context
200   -
201   -
202   -from django_modalview.generic.base import ModalTemplateView
203   -
204   -class MyModal(ModalTemplateView):
205   - '''
206   - This modal inherit of ModalTemplateView, so it just display a text without logic.
207   - '''
208   - def __init__(self, *args, **kwargs):
209   - '''
210   - You have to call the init method of the parent, before to overide the values:
211   - - title: The title display in the modal-header
212   - - icon: The css class that define the modal's icon
213   - - description: The content of the modal.
214   - - close_button: A button object that has several attributes.(explain below)
215   - '''
216   - super(MyModal, self).__init__(*args, **kwargs)
217   - self.title = "My modal"
218   - self.description = "This is my description"
219   - self.icon = "icon-mymodal"
... ...
requirements.txt
1 1 click==6.6
  2 +decorator==4.0.10
2 3 deps==0.1.0
3 4 dj-database-url==0.4.1
4 5 Django==1.10
... ... @@ -19,5 +20,6 @@ psycopg2==2.6.2
19 20 pycpfcnpj==1.0.2
20 21 six==1.10.0
21 22 slugify==0.0.1
  23 +validators==0.11.0
22 24 virtualenv==15.0.3
23 25 Werkzeug==0.11.11
... ...
users/templates/list_users.html
... ... @@ -103,5 +103,3 @@
103 103 {% endif %}
104 104 {% endblock %}
105 105  
106   -{% block rightbar %}
107   -{% endblock rightbar %}
... ...