Commit e6cdad586cbcfaaddaa7eea251e5da5e3ea992a9

Authored by Jailson Dias
2 parents 7f4810ac 5a7d7934

Merge branch 'dev' of https://github.com/amadeusproject/amadeuslms into dev

core/context_processors.py
@@ -5,6 +5,6 @@ def notifications(request): @@ -5,6 +5,6 @@ def notifications(request):
5 context['notifications'] = None 5 context['notifications'] = None
6 if request.user.is_authenticated: 6 if request.user.is_authenticated:
7 return { 7 return {
8 - 'notifications': Notification.objects.filter(user= request.user, read=False).order_by('-datetime') 8 + 'notifications': Notification.objects.filter(user= request.user, read=False).order_by('-datetime')[0:5]
9 } 9 }
10 return context 10 return context
@@ -15,31 +15,7 @@ class RegisterUserForm(forms.ModelForm): @@ -15,31 +15,7 @@ class RegisterUserForm(forms.ModelForm):
15 15
16 def validate_cpf(self, cpf): 16 def validate_cpf(self, cpf):
17 cpf = ''.join(re.findall('\d', str(cpf))) 17 cpf = ''.join(re.findall('\d', str(cpf)))
18 - # print(cpf)  
19 -  
20 - # if (not cpf) or (len(cpf) < 11):  
21 - # return False  
22 -  
23 - # #Get only the first 9 digits and generate other 2  
24 - # _int = map(int, cpf)  
25 - # integer = list(map(int, cpf))  
26 - # new = integer[:9]  
27 -  
28 - # while len(new) < 11:  
29 - # r = sum([(len(new) + 1 - i)* v for i, v in enumerate(new)]) % 11  
30 -  
31 - # if r > 1:  
32 - # f = 11 - r  
33 - # else:  
34 - # f = 0  
35 - # new.append(f)  
36 -  
37 - # #if generated number is the same(original) the cpf is valid  
38 - # new2 = list(new)  
39 - # if new2 == _int:  
40 - # return cpf  
41 - # else:  
42 - # return False 18 +
43 if cpfcnpj.validate(cpf): 19 if cpfcnpj.validate(cpf):
44 return True 20 return True
45 return False 21 return False
core/static/css/base/amadeus.css
@@ -266,7 +266,6 @@ li.alert_li:hover{background-color:#eee} @@ -266,7 +266,6 @@ li.alert_li:hover{background-color:#eee}
266 a.alert_message{color : grey} 266 a.alert_message{color : grey}
267 a.alert_message:hover{color : grey} 267 a.alert_message:hover{color : grey}
268 268
269 -/*=================== Ailson - Please Don't touch*/  
270 .breadcrumb .divider{ 269 .breadcrumb .divider{
271 display: none; 270 display: none;
272 } 271 }
core/static/js/base/amadeus.js
@@ -126,4 +126,14 @@ function validarCpfSemAlert(campo,nome,idElementoMensagemErro){ @@ -126,4 +126,14 @@ function validarCpfSemAlert(campo,nome,idElementoMensagemErro){
126 return true; 126 return true;
127 } 127 }
128 return retorno; 128 return retorno;
129 -}  
130 \ No newline at end of file 129 \ No newline at end of file
  130 +}
  131 +
  132 +/*
  133 +This functions get the next 5 notifications from the user given a "step"(an amount) of previous notifications
  134 +*/
  135 +function getNotifications(step){
  136 + $.get('/getNotifications',
  137 + {'steps':step, 'amount': 5}, function(data){
  138 + console.log(data);
  139 + });
  140 +}
core/static/js/base/header.js
1 $(document).ready(function(){ 1 $(document).ready(function(){
2 $('[data-toggle="tooltip"]').tooltip(); //activate tooltip on all elements that has attribute data-toggle 2 $('[data-toggle="tooltip"]').tooltip(); //activate tooltip on all elements that has attribute data-toggle
3 -});  
4 \ No newline at end of file 3 \ No newline at end of file
  4 +});
  5 +
  6 +
  7 +/*
  8 +
  9 +*/
  10 +function getNotifications(step){
  11 + $.ajax('/getNotifications',{
  12 + steps: step,
  13 + amount: 5,
  14 + sucess: function(response){
  15 +
  16 + }
  17 + });
  18 +}
  19 +
  20 +
  21 +/*
  22 +
  23 +*/
  24 +function checkIfNewNotification(){
  25 +
  26 +}
5 \ No newline at end of file 27 \ No newline at end of file
core/templates/base.html
@@ -38,6 +38,7 @@ @@ -38,6 +38,7 @@
38 <script type="text/javascript">$.material.init()</script> 38 <script type="text/javascript">$.material.init()</script>
39 39
40 <!--Javascript block for specific-app ones --> 40 <!--Javascript block for specific-app ones -->
  41 + <script src="{% static 'js/base/amadeus.js' %}"></script>
41 {% block style %} 42 {% block style %}
42 {% endblock %} 43 {% endblock %}
43 </head> 44 </head>
@@ -60,40 +61,10 @@ @@ -60,40 +61,10 @@
60 <a class="dropdown-toggle" data-toggle="dropdown"> <span class="badge notification-count">{{notifications.count}}</span><i class="fa fa-bell" aria-hidden="true"></i></a> 61 <a class="dropdown-toggle" data-toggle="dropdown"> <span class="badge notification-count">{{notifications.count}}</span><i class="fa fa-bell" aria-hidden="true"></i></a>
61 <ul id="notification-dropdown" class="dropdown-menu"> 62 <ul id="notification-dropdown" class="dropdown-menu">
62 <li class="dropdown-header">Notifications</li> 63 <li class="dropdown-header">Notifications</li>
63 - {% for notification in notifications %}  
64 - {% if notification.actor %} <!-- if the notification has a user-->  
65 - <li>  
66 - <a href="{% url 'core:notification_read' notification.id %}"><div class="list-group-item">  
67 - <div class="row-picture">  
68 - <img class="circle" src="http://lorempixel.com/56/56/people/1" alt="icon">  
69 - <div class="least-content pull-right">{{ notification.datetime }}</div>  
70 - </div>  
71 - <div class="row-content">  
72 - <p class="list-group-item-text">{{ notification.message }}</p>  
73 - </div>  
74 - </div>  
75 - </a>  
76 - </li>  
77 - {% else %}  
78 - <li>  
79 - <a href="{% url 'core:notification_read' notification.id %}">  
80 - <div class="list-group-item">  
81 - <div class="row-action-primary">  
82 - <i class="material-icons">folder</i>  
83 - </div>  
84 - <div class="row-content">  
85 -  
86 - <div class="least-content pull-right">{{ notification.datetime }}</div>  
87 -  
88 - <p class="list-group-item-text">{{ notification.message }}</p>  
89 - </div>  
90 - </a>  
91 - </li>  
92 - {% endif %}  
93 - {% endfor %} 64 + {% include "notifications.html" %}
94 65
95 <li> 66 <li>
96 - <a> 67 + <a onclick="getNotifications(5)">
97 <div class="list-group-item"> 68 <div class="list-group-item">
98 <div class="row-content"> 69 <div class="row-content">
99 <p class="list-group-item-text">See More</p> 70 <p class="list-group-item-text">See More</p>
core/templates/notifications.html 0 → 100644
@@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
  1 +{% for notification in notifications %}
  2 + {% if notification.actor %} <!-- if the notification has a user-->
  3 + <li>
  4 + <a href="{% url 'core:notification_read' notification.id %}"><div class="list-group-item">
  5 + <div class="row-picture">
  6 + <img class="circle" src="http://lorempixel.com/56/56/people/1" alt="icon">
  7 + <div class="least-content pull-right">{{ notification.datetime }}</div>
  8 + </div>
  9 + <div class="row-content">
  10 + <p class="list-group-item-text">{{ notification.message }}</p>
  11 + </div>
  12 + </div>
  13 + </a>
  14 + </li>
  15 + {% else %}
  16 + <li>
  17 + <a href="{% url 'core:notification_read' notification.id %}">
  18 + <div class="list-group-item">
  19 + <div class="row-action-primary">
  20 + <i class="material-icons">folder</i>
  21 + </div>
  22 + <div class="row-content">
  23 +
  24 + <div class="least-content pull-right">{{ notification.datetime }}</div>
  25 +
  26 + <p class="list-group-item-text">{{ notification.message }}</p>
  27 + </div>
  28 + </a>
  29 + </li>
  30 + {% endif %}
  31 +{% endfor %}
0 \ No newline at end of file 32 \ No newline at end of file
core/templates/register_user.html
@@ -8,11 +8,16 @@ @@ -8,11 +8,16 @@
8 8
9 9
10 {% block content %} 10 {% block content %}
11 - {% if message %}  
12 - <div class="alert alert-danger">  
13 - {{message}}  
14 - </div>  
15 - {% endif %} 11 + {% if messages %}
  12 + {% for message in messages %}
  13 + <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert">
  14 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  15 + <span aria-hidden="true">&times;</span>
  16 + </button>
  17 + <p>{{ message }}</p>
  18 + </div>
  19 + {% endfor %}
  20 + {% endif %}
16 <div class="row logo-row"> 21 <div class="row logo-row">
17 <div class="col-lg-offset-2 col-lg-9"> 22 <div class="col-lg-offset-2 col-lg-9">
18 <img src="{% static 'img/amadeus.png' %}" class="img-responsive center-block " alt="logo amadeus" id="logo"> 23 <img src="{% static 'img/amadeus.png' %}" class="img-responsive center-block " alt="logo amadeus" id="logo">
@@ -29,7 +34,11 @@ @@ -29,7 +34,11 @@
29 <legend>{% trans 'User Register' %}</legend> 34 <legend>{% trans 'User Register' %}</legend>
30 {% for field in form %} 35 {% for field in form %}
31 <div class="form-group is-empy{% if form.has_error %} has-error {% endif %} is-fileinput"> 36 <div class="form-group is-empy{% if form.has_error %} has-error {% endif %} is-fileinput">
32 - <label for="{{ field.auto_id }}" class="col-md-4 control-label">{{ field.label }}</label> 37 + {% if field.field.required %}
  38 + <label for="{{ field.auto_id }}" class="col-md-4 control-label">{{ field.label }}<span>*</span></label>
  39 + {% else %}
  40 + <label for="{{ field.auto_id }}" class="col-md-4 control-label">{{ field.label }}</label>
  41 + {% endif %}
33 <div class="col-md-8"> 42 <div class="col-md-8">
34 {% if field.auto_id == 'id_birth_date' %} 43 {% if field.auto_id == 'id_birth_date' %}
35 {% render_field field class='form-control input-sm' type='date' %} 44 {% render_field field class='form-control input-sm' type='date' %}
@@ -81,5 +90,4 @@ @@ -81,5 +90,4 @@
81 </div> 90 </div>
82 91
83 <br clear="all" /> 92 <br clear="all" />
84 - <script src="{% static 'js/base/amadeus.js' %}"></script>  
85 {% endblock %} 93 {% endblock %}
@@ -89,7 +89,7 @@ class RegisterUserTestCase(TestCase): @@ -89,7 +89,7 @@ class RegisterUserTestCase(TestCase):
89 } 89 }
90 90
91 response = self.client.post(self.url, data) 91 response = self.client.post(self.url, data)
92 - self.assertFormError(response, 'form', 'email', 'Insira um endereço de email válido.') 92 + self.assertFormError(response, 'form', 'email', 'Enter a valid email address.')
93 93
94 data = { 94 data = {
95 'username': '', 95 'username': '',
@@ -102,7 +102,7 @@ class RegisterUserTestCase(TestCase): @@ -102,7 +102,7 @@ class RegisterUserTestCase(TestCase):
102 'gender': 'F', 102 'gender': 'F',
103 } 103 }
104 response = self.client.post(self.url, data) 104 response = self.client.post(self.url, data)
105 - self.assertFormError(response, 'form', 'username', 'Este campo é obrigatório.') 105 + self.assertFormError(response, 'form', 'username', 'This field is required.')
106 106
107 class RememberPasswordTestCase(TestCase): 107 class RememberPasswordTestCase(TestCase):
108 108
@@ -194,7 +194,7 @@ class UpdateUserTestCase(TestCase): @@ -194,7 +194,7 @@ class UpdateUserTestCase(TestCase):
194 'gender': 'F', 194 'gender': 'F',
195 } 195 }
196 response = self.client.post(self.url, data) 196 response = self.client.post(self.url, data)
197 - self.assertFormError(response, 'form', 'username', 'Este campo é obrigatório.') 197 + self.assertFormError(response, 'form', 'username', 'This field is required.')
198 198
199 199
200 class DeleteUserTestCase(TestCase): 200 class DeleteUserTestCase(TestCase):
@@ -9,5 +9,6 @@ urlpatterns = [ @@ -9,5 +9,6 @@ urlpatterns = [
9 url(r'^register/$', views.RegisterUser.as_view(), name='register'), 9 url(r'^register/$', views.RegisterUser.as_view(), name='register'),
10 url(r'^remember_password/$', views.remember_password, name='remember_password'), 10 url(r'^remember_password/$', views.remember_password, name='remember_password'),
11 url(r'^logout/$', auth_views.logout, {'next_page': 'core:home'}, name='logout'), 11 url(r'^logout/$', auth_views.logout, {'next_page': 'core:home'}, name='logout'),
12 - url(r'^notification/([0-9]+)/$', views.processNotification, name='notification_read') 12 + url(r'^notification/([0-9]+)/$', views.processNotification, name='notification_read'),
  13 + url(r'^getNotifications/$', views.getNotifications, name='getNotifications'),
13 ] 14 ]
@@ -5,8 +5,9 @@ from django.contrib.auth.mixins import LoginRequiredMixin @@ -5,8 +5,9 @@ from django.contrib.auth.mixins import LoginRequiredMixin
5 from .decorators import log_decorator 5 from .decorators import log_decorator
6 from django.contrib import messages 6 from django.contrib import messages
7 from django.shortcuts import render, redirect 7 from django.shortcuts import render, redirect
  8 +from django.template.loader import render_to_string
8 from django.views.generic import CreateView, UpdateView 9 from django.views.generic import CreateView, UpdateView
9 -from django.http import HttpResponse 10 +from django.http import HttpResponse, JsonResponse
10 from django.core.mail import send_mail,BadHeaderError 11 from django.core.mail import send_mail,BadHeaderError
11 from django.conf import settings 12 from django.conf import settings
12 from core.mixins import NotificationMixin 13 from core.mixins import NotificationMixin
@@ -95,6 +96,28 @@ def processNotification(self, notificationId): @@ -95,6 +96,28 @@ def processNotification(self, notificationId):
95 notification.save() 96 notification.save()
96 return redirect(notification.action_resource.resource.url) 97 return redirect(notification.action_resource.resource.url)
97 98
  99 +
  100 +
  101 +
  102 +def getNotifications(request):
  103 + context = {}
  104 + if request.user.is_authenticated:
  105 +
  106 + steps = int(request.GET['steps'])
  107 + amount = int(request.GET['amount'])
  108 + notifications = Notification.objects.filter(user= request.user, read=False).order_by('-datetime')[steps:steps+amount]
  109 + context['notifications'] = notifications
  110 + else: #go to login page
  111 + return HttpResponse('teste')
  112 +
  113 +
  114 + html = render_to_string("notifications.html", context)
  115 + print(html)
  116 + return HttpResponse(html)
  117 +
  118 +
  119 +
  120 +
98 # class LoginClass(LoginView): 121 # class LoginClass(LoginView):
99 # template_name='index.html' 122 # template_name='index.html'
100 # 123 #
courses/templates/subject/form_view_teacher.html
@@ -32,16 +32,6 @@ @@ -32,16 +32,6 @@
32 <div class="modal-body"> 32 <div class="modal-body">
33 <section> 33 <section>
34 <div class="forum_topics"></div> 34 <div class="forum_topics"></div>
35 - <div class="form-group">  
36 - <div class="input-group">  
37 - <textarea type="text" id="addon3a" class="form-control" placeholder="{% trans 'Post a comment...' %}"></textarea>  
38 - <span class="input-group-btn">  
39 - <button type="button" class="btn btn-fab btn-fab-mini">  
40 - <i class="material-icons">send</i>  
41 - </button>  
42 - </span>  
43 - </div>  
44 - </div>  
45 </section> 35 </section>
46 </div> 36 </div>
47 <div class="modal-footer"> 37 <div class="modal-footer">
forum/forms.py
1 from django import forms 1 from django import forms
2 from django.utils.translation import ugettext_lazy as _ 2 from django.utils.translation import ugettext_lazy as _
3 -from .models import Forum, PostAnswer 3 +from .models import Forum, Post, PostAnswer
4 4
5 class ForumForm(forms.ModelForm): 5 class ForumForm(forms.ModelForm):
6 6
@@ -19,6 +19,19 @@ class ForumForm(forms.ModelForm): @@ -19,6 +19,19 @@ class ForumForm(forms.ModelForm):
19 'description': forms.Textarea(attrs={'cols': 80, 'rows': 5}), 19 'description': forms.Textarea(attrs={'cols': 80, 'rows': 5}),
20 } 20 }
21 21
  22 +class PostForm(forms.ModelForm):
  23 +
  24 + class Meta:
  25 + model = Post
  26 + fields = ('message', 'forum', )
  27 + labels = {
  28 + 'message': _('Message')
  29 + }
  30 + widgets = {
  31 + 'message': forms.Textarea(attrs={'cols': 80, 'rows': 3}),
  32 + 'forum': forms.HiddenInput(),
  33 + }
  34 +
22 class PostAnswerForm(forms.ModelForm): 35 class PostAnswerForm(forms.ModelForm):
23 36
24 class Meta: 37 class Meta:
forum/models.py
@@ -41,6 +41,15 @@ class Post(models.Model): @@ -41,6 +41,15 @@ class Post(models.Model):
41 def __str__(self): 41 def __str__(self):
42 return ''.join([self.user.name, " / ", str(self.post_date)]) 42 return ''.join([self.user.name, " / ", str(self.post_date)])
43 43
  44 + def is_modified(self):
  45 + create = self.post_date.strftime("%Y-%m-%d %H:%M:%S")
  46 + edit = self.modification_date.strftime("%Y-%m-%d %H:%M:%S")
  47 +
  48 + if create != edit:
  49 + return True
  50 +
  51 + return False
  52 +
44 """ 53 """
45 It represents an answer to a forum's post 54 It represents an answer to a forum's post
46 """ 55 """
forum/static/js/forum.js
  1 +function getCookie(name) {
  2 + var cookieValue = null;
  3 + if (document.cookie && document.cookie !== '') {
  4 + var cookies = document.cookie.split(';');
  5 + for (var i = 0; i < cookies.length; i++) {
  6 + var cookie = jQuery.trim(cookies[i]);
  7 + // Does this cookie string begin with the name we want?
  8 + if (cookie.substring(0, name.length + 1) === (name + '=')) {
  9 + cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
  10 + break;
  11 + }
  12 + }
  13 + }
  14 + return cookieValue;
  15 +}
  16 +
  17 +
1 /* 18 /*
2 * 19 *
3 * Function to load forum to modal 20 * Function to load forum to modal
@@ -9,51 +26,100 @@ function showForum(url, forum_id) { @@ -9,51 +26,100 @@ function showForum(url, forum_id) {
9 data: {'forum_id': forum_id}, 26 data: {'forum_id': forum_id},
10 success: function(data) { 27 success: function(data) {
11 $(".forum_topics").html(data); 28 $(".forum_topics").html(data);
  29 +
  30 + var frm = $('#form_post');
  31 + frm.submit(function () {
  32 + $.ajax({
  33 + type: frm.attr('method'),
  34 + url: frm.attr('action'),
  35 + data: frm.serialize(),
  36 + success: function (data) {
  37 + $("#posts_list").append(data);
  38 + frm[0].reset();
  39 + },
  40 + error: function(data) {
  41 + console.log(frm.serialize());
  42 + console.log('Error');
  43 + }
  44 + });
  45 + return false;
  46 + });
12 } 47 }
13 }); 48 });
14 49
15 $('#forumModal').modal(); 50 $('#forumModal').modal();
16 } 51 }
17 52
18 -function answer(id, url) { 53 +/*
  54 +*
  55 +* Function to load form to edit post
  56 +*
  57 +*/
  58 +function edit_post(url, post_id) {
19 $.ajax({ 59 $.ajax({
20 - url: url, 60 + url: url,
21 success: function(data) { 61 success: function(data) {
22 - $("#post_"+id).find(".answer_post").html(data); 62 + $("#post_"+post_id).find(".post_content").hide();
  63 + $("#post_"+post_id).find(".post_content").after(data);
  64 +
  65 + var frm = $("#post_"+post_id).find(".edit_post_form");
  66 + frm.submit(function () {
  67 + $.ajax({
  68 + type: frm.attr('method'),
  69 + url: frm.attr('action'),
  70 + data: frm.serialize(),
  71 + success: function (data) {
  72 + $("#post_"+post_id).parent().after(data);
  73 + frm.parent().parent().remove();
  74 + },
  75 + error: function(data) {
  76 + console.log(frm.serialize());
  77 + console.log('Error');
  78 + }
  79 + });
  80 + return false;
  81 + });
23 } 82 }
24 }); 83 });
25 -  
26 - $("#post_"+id).find(".answer_post").show();  
27 } 84 }
28 85
29 -function showPosts(url, forum) {  
30 - if ($("#collapse" + forum).hasClass('in')) {  
31 - $("#collapse" + forum).collapse('hide');  
32 - } else {  
33 - $.ajax({  
34 - url: url,  
35 - data: {'forum': forum},  
36 - success: function(data) {  
37 - $("#collapse" + forum).find(".well").html(data);  
38 - }  
39 - }); 86 +/*
  87 +*
  88 +* Function to cancel post edition
  89 +*
  90 +*/
  91 +function cancelEditPost(post_id) {
  92 + $("#post_"+post_id).find(".post_content").show();
  93 + $("#post_"+post_id).find(".edit_post_form").remove();
  94 +}
40 95
41 - $("#collapse" + forum).collapse('show');  
42 - } 96 +/*
  97 +*
  98 +* Function to delete a post
  99 +*
  100 +*/
  101 +function delete_post(url, post) {
  102 + var csrftoken = getCookie('csrftoken');
  103 +
  104 + $.ajax({
  105 + method: 'post',
  106 + beforeSend: function (request) {
  107 + request.setRequestHeader('X-CSRFToken', csrftoken);
  108 + },
  109 + url: url,
  110 + success: function(data) {
  111 + $("#post_"+post).remove();
  112 + }
  113 + });
43 } 114 }
44 115
45 -function showPostsAnswers(url, post) {  
46 - if ($("#collapse" + post).hasClass('in')) {  
47 - $("#collapse" + post).collapse('hide');  
48 - } else {  
49 - $.ajax({  
50 - url: url,  
51 - data: {'post': post},  
52 - success: function(data) {  
53 - $("#collapse" + post).find(".well").html(data);  
54 - }  
55 - }); 116 +function answer(id, url) {
  117 + $.ajax({
  118 + url: url,
  119 + success: function(data) {
  120 + $("#post_"+id).find(".answer_post").html(data);
  121 + }
  122 + });
56 123
57 - $("#collapse" + post).collapse('show');  
58 - } 124 + $("#post_"+id).find(".answer_post").show();
59 } 125 }
60 \ No newline at end of file 126 \ No newline at end of file
forum/templates/forum/forum_list.html
1 {% load i18n permission_tags list_post %} 1 {% load i18n permission_tags list_post %}
  2 +{% load widget_tweaks %}
2 3
3 <div class="comments-list"> 4 <div class="comments-list">
4 <div class="section-heading"> 5 <div class="section-heading">
@@ -8,7 +9,45 @@ @@ -8,7 +9,45 @@
8 </div> 9 </div>
9 </div> 10 </div>
10 11
11 -{% list_posts request forum %} 12 +<div id="posts_list">
  13 + {% list_posts request forum %}
  14 +</div>
  15 +
  16 +<form id="form_post" method="post" action="{% url 'forum:create_post' %}" enctype="multipart/form-data">
  17 + {% csrf_token %}
  18 + {% for field in form %}
  19 + {% if field.field.widget.input_type == 'hidden' %}
  20 + {% render_field field class='form-control' value=forum.id %}
  21 + {% else %}
  22 + <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput">
  23 + <div class="input-group">
  24 + {% render_field field class='form-control' placeholder="Post a message" %}
  25 + <span class="help-block">{{ field.help_text }}</span>
  26 + {% if field.errors %}
  27 + <div class="row">
  28 + <br />
  29 + <div class="alert alert-danger alert-dismissible" role="alert">
  30 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  31 + <span aria-hidden="true">&times;</span>
  32 + </button>
  33 + <ul>
  34 + {% for error in field.errors %}
  35 + <li>{{ error }}</li>
  36 + {% endfor %}
  37 + </ul>
  38 + </div>
  39 + </div>
  40 + {% endif %}
  41 + <span class="input-group-btn">
  42 + <button type="submit" class="btn btn-fab btn-fab-mini">
  43 + <i class="material-icons">send</i>
  44 + </button>
  45 + </span>
  46 + </div>
  47 + </div>
  48 + {% endif %}
  49 + {% endfor %}
  50 +</form>
12 51
13 <!--{% if foruns|length > 0 %} 52 <!--{% if foruns|length > 0 %}
14 {% for forum in foruns %} 53 {% for forum in foruns %}
forum/templates/post/post_list.html
@@ -11,22 +11,30 @@ @@ -11,22 +11,30 @@
11 <i class="material-icons">reply</i> 11 <i class="material-icons">reply</i>
12 </a> 12 </a>
13 {% if request.user|has_role:'system_admin' or request.user|has_role:'professor' and request.user == post.user %} 13 {% if request.user|has_role:'system_admin' or request.user|has_role:'professor' and request.user == post.user %}
  14 + {% csrf_token %}
14 <div class="btn-group icon-more-horiz"> 15 <div class="btn-group icon-more-horiz">
15 <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> 16 <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
16 <i class="material-icons">more_horiz</i> 17 <i class="material-icons">more_horiz</i>
17 </a> 18 </a>
18 <ul class="dropdown-menu" aria-labelledby="dropdownMenu1"> 19 <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
19 - <li><a href="javascript:void(0)"><i class="material-icons">create</i> {% trans 'Edit' %}</a></li>  
20 - <li><a href="javascript:void(0)"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li> 20 + <li><a href="javascript:edit_post('{% url 'forum:update_post' post.id %}', '{{ post.id }}')"><i class="material-icons">create</i> {% trans 'Edit' %}</a></li>
  21 + <li><a href="javascript:javascript:delete_post('{% url 'forum:delete_post' post.id %}', '{{ post.id }}')"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li>
21 </ul> 22 </ul>
22 </div> 23 </div>
23 {% endif %} 24 {% endif %}
24 </div> 25 </div>
25 </h3> 26 </h3>
26 - <div class="card-data">  
27 - <p class="comment-date"><i class="fa fa-clock-o"></i> {{ post.post_date }}</p> 27 + <div class="post_content">
  28 + <div class="card-data">
  29 + <p class="comment-date">
  30 + <i class="fa fa-clock-o"></i> {{ post.post_date }}
  31 + {% if post.is_modified %}
  32 + <em> - {% trans 'Edited' %}</em>
  33 + {% endif %}
  34 + </p>
  35 + </div>
  36 + <p class="comment-text">{{ post.message|linebreaks }}</p>
28 </div> 37 </div>
29 - <p class="comment-text">{{ post.message|linebreaks }}</p>  
30 <div class="answer_post"></div> 38 <div class="answer_post"></div>
31 </div> 39 </div>
32 </div> 40 </div>
forum/templates/post/post_render.html 0 → 100644
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +{% load i18n permission_tags %}
  2 +
  3 +<div class="row">
  4 + <div id="post_{{ post.id }}" class="col-sm-12 col-xs-12">
  5 + <h3 class="user-name">
  6 + {{ post.user }}
  7 + <div class="pull-right">
  8 + <a href="javascript:answer('{{ post.id }}', '{% url 'forum:reply_post' %}');">
  9 + <i class="material-icons">reply</i>
  10 + </a>
  11 + {% if request.user|has_role:'system_admin' or request.user|has_role:'professor' and request.user == post.user %}
  12 + {% csrf_token %}
  13 + <div class="btn-group icon-more-horiz">
  14 + <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
  15 + <i class="material-icons">more_horiz</i>
  16 + </a>
  17 + <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
  18 + <li><a href="javascript:edit_post('{% url 'forum:update_post' post.id %}', '{{ post.id }}')"></li>
  19 + <li><a href="javascript:delete_post('{% url 'forum:delete_post' post.id %}', '{{ post.id }}')"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li>
  20 + </ul>
  21 + </div>
  22 + {% endif %}
  23 + </div>
  24 + </h3>
  25 + <div class="post_content">
  26 + <div class="card-data">
  27 + <p class="comment-date">
  28 + <i class="fa fa-clock-o"></i> {{ post.post_date }}
  29 + {% if post.post_date != post.modifiction_date %}
  30 + <em> - {% trans 'Edited' %}</em>
  31 + {% endif %}
  32 + </p>
  33 + </div>
  34 + <p class="comment-text">{{ post.message|linebreaks }}</p>
  35 + </div>
  36 + <div class="answer_post"></div>
  37 + </div>
  38 +</div>
0 \ No newline at end of file 39 \ No newline at end of file
forum/templates/post/post_update_form.html 0 → 100644
@@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
  1 +{% load i18n permission_tags list_post %}
  2 +{% load widget_tweaks %}
  3 +
  4 +<form class="edit_post_form" method="post" action="{% url 'forum:update_post' post.id %}" enctype="multipart/form-data">
  5 + {% csrf_token %}
  6 + {% for field in form %}
  7 + {% if field.field.widget.input_type == 'hidden' %}
  8 + {% render_field field class='form-control' %}
  9 + {% else %}
  10 + <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput">
  11 + <div class="input-group">
  12 + {% render_field field class='form-control' placeholder="Post a message" %}
  13 + <span class="help-block">{{ field.help_text }}</span>
  14 + {% if field.errors %}
  15 + <div class="row">
  16 + <br />
  17 + <div class="alert alert-danger alert-dismissible" role="alert">
  18 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  19 + <span aria-hidden="true">&times;</span>
  20 + </button>
  21 + <ul>
  22 + {% for error in field.errors %}
  23 + <li>{{ error }}</li>
  24 + {% endfor %}
  25 + </ul>
  26 + </div>
  27 + </div>
  28 + {% endif %}
  29 + </div>
  30 + </div>
  31 + <div class="pull-right">
  32 + <button type="button" onclick="cancelEditPost('{{ post.id }}')" class="btn btn-danger btn-raised">{% trans 'Cancel' %}</button>
  33 + <button type="submit" class="btn btn-primary btn-raised">{% trans 'Save changes' %}</button>
  34 + </div>
  35 + {% endif %}
  36 + {% endfor %}
  37 +</form>
0 \ No newline at end of file 38 \ No newline at end of file
forum/templates/post_answers/post_answer_form.html
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
25 </div> 25 </div>
26 {% endif %} 26 {% endif %}
27 <span class="input-group-btn"> 27 <span class="input-group-btn">
28 - <button type="button" class="btn btn-fab btn-fab-mini"> 28 + <button type="submit" class="btn btn-fab btn-fab-mini">
29 <i class="material-icons">send</i> 29 <i class="material-icons">send</i>
30 </button> 30 </button>
31 </span> 31 </span>
forum/templatetags/list_post.py
@@ -14,6 +14,6 @@ def list_posts(request, forum): @@ -14,6 +14,6 @@ def list_posts(request, forum):
14 'request': request, 14 'request': request,
15 } 15 }
16 16
17 - context['posts'] = Post.objects.filter(forum = forum) 17 + context['posts'] = Post.objects.filter(forum = forum).order_by('post_date')
18 18
19 return context 19 return context
20 \ No newline at end of file 20 \ No newline at end of file
@@ -6,7 +6,11 @@ from . import views @@ -6,7 +6,11 @@ from . import views
6 urlpatterns = [ 6 urlpatterns = [
7 url(r'^$', views.ForumIndex.as_view(), name='index'), 7 url(r'^$', views.ForumIndex.as_view(), name='index'),
8 url(r'^create$', views.CreateForumView.as_view(), name='create'), 8 url(r'^create$', views.CreateForumView.as_view(), name='create'),
9 - url(r'^posts$', views.PostIndex.as_view(), name='posts'), 9 + url(r'^create_post$', views.CreatePostView.as_view(), name='create_post'),
  10 + url(r'^update_post/(?P<pk>[\w_-]+)/$', views.PostUpdateView.as_view(), name='update_post'),
  11 + url(r'^delete_post/(?P<pk>[\w_-]+)/$', views.PostDeleteView.as_view(), name='delete_post'),
  12 + url(r'^render_post/([\w_-]+)/$', views.render_post, name='render_post'),
  13 + url(r'^post_deleted/$', views.post_deleted, name='deleted_post'),
10 url(r'^post_answers$', views.PostAnswerIndex.as_view(), name='post_answers'), 14 url(r'^post_answers$', views.PostAnswerIndex.as_view(), name='post_answers'),
11 url(r'^reply_post$', views.CreatePostAnswerView.as_view(), name='reply_post'), 15 url(r'^reply_post$', views.CreatePostAnswerView.as_view(), name='reply_post'),
12 ] 16 ]
forum/views.py
  1 +from django.http import HttpResponse
1 from django.shortcuts import render, get_object_or_404 2 from django.shortcuts import render, get_object_or_404
2 -from django.core.urlresolvers import reverse_lazy 3 +from django.core.urlresolvers import reverse, reverse_lazy
3 from django.utils.translation import ugettext_lazy as _ 4 from django.utils.translation import ugettext_lazy as _
4 from django.views import generic 5 from django.views import generic
5 from django.contrib.auth.mixins import LoginRequiredMixin 6 from django.contrib.auth.mixins import LoginRequiredMixin
@@ -7,7 +8,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin @@ -7,7 +8,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin
7 from .models import Forum, Post, PostAnswer 8 from .models import Forum, Post, PostAnswer
8 from courses.models import Topic 9 from courses.models import Topic
9 10
10 -from .forms import ForumForm, PostAnswerForm 11 +from .forms import ForumForm, PostForm, PostAnswerForm
11 12
12 class ForumIndex(LoginRequiredMixin, generic.ListView): 13 class ForumIndex(LoginRequiredMixin, generic.ListView):
13 login_url = reverse_lazy("core:home") 14 login_url = reverse_lazy("core:home")
@@ -20,6 +21,12 @@ class ForumIndex(LoginRequiredMixin, generic.ListView): @@ -20,6 +21,12 @@ class ForumIndex(LoginRequiredMixin, generic.ListView):
20 forum_id = self.request.GET.get('forum_id', 0) 21 forum_id = self.request.GET.get('forum_id', 0)
21 22
22 context = Forum.objects.get(id = forum_id) 23 context = Forum.objects.get(id = forum_id)
  24 +
  25 + return context
  26 +
  27 + def get_context_data(self, **kwargs):
  28 + context = super(ForumIndex, self).get_context_data(**kwargs)
  29 + context['form'] = PostForm()
23 30
24 return context 31 return context
25 32
@@ -29,19 +36,56 @@ class CreateForumView(LoginRequiredMixin, generic.edit.CreateView): @@ -29,19 +36,56 @@ class CreateForumView(LoginRequiredMixin, generic.edit.CreateView):
29 form_class = ForumForm 36 form_class = ForumForm
30 success_url = reverse_lazy('forum:index') 37 success_url = reverse_lazy('forum:index')
31 38
32 -class PostIndex(LoginRequiredMixin, generic.ListView): 39 +class CreatePostView(LoginRequiredMixin, generic.edit.CreateView):
33 login_url = reverse_lazy("core:home") 40 login_url = reverse_lazy("core:home")
34 redirect_field_name = 'next' 41 redirect_field_name = 'next'
35 42
36 - template_name = "post/post_list.html"  
37 - context_object_name = 'posts' 43 + form_class = PostForm
38 44
39 - def get_queryset(self):  
40 - forum = get_object_or_404(Forum, slug = self.request.GET.get('forum', '')) 45 + def form_valid(self, form):
  46 + self.object = form.save(commit = False)
  47 + self.object.user = self.request.user
41 48
42 - context = Post.objects.filter(forum = forum) 49 + self.object.save()
43 50
44 - return context 51 + return super(CreatePostView, self).form_valid(form)
  52 +
  53 + def get_success_url(self):
  54 + self.success_url = reverse('forum:render_post', args = (self.object.id, ))
  55 +
  56 + return self.success_url
  57 +
  58 +def render_post(request, post):
  59 + last_post = get_object_or_404(Post, id = post)
  60 +
  61 + context = {}
  62 + context['post'] = last_post
  63 +
  64 + return render(request, "post/post_render.html", context)
  65 +
  66 +class PostUpdateView(LoginRequiredMixin, generic.UpdateView):
  67 + login_url = reverse_lazy("core:home")
  68 + redirect_field_name = 'next'
  69 +
  70 + form_class = PostForm
  71 + model = Post
  72 + template_name = "post/post_update_form.html"
  73 +
  74 + def get_success_url(self):
  75 + self.success_url = reverse('forum:render_post', args = (self.object.id, ))
  76 +
  77 + return self.success_url
  78 +
  79 +class PostDeleteView(LoginRequiredMixin, generic.DeleteView):
  80 + login_url = reverse_lazy("core:home")
  81 + redirect_field_name = 'next'
  82 +
  83 + model = Post
  84 + pk_url_kwarg = 'pk'
  85 + success_url = reverse_lazy('forum:deleted_post')
  86 +
  87 +def post_deleted(request):
  88 + return HttpResponse(_("Post deleted successfully."))
45 89
46 class PostAnswerIndex(LoginRequiredMixin, generic.ListView): 90 class PostAnswerIndex(LoginRequiredMixin, generic.ListView):
47 login_url = reverse_lazy("core:home") 91 login_url = reverse_lazy("core:home")
requirements.txt
@@ -10,7 +10,6 @@ itsdangerous==0.24 @@ -10,7 +10,6 @@ itsdangerous==0.24
10 Jinja2==2.8 10 Jinja2==2.8
11 MarkupSafe==0.23 11 MarkupSafe==0.23
12 Pillow==3.3.1 12 Pillow==3.3.1
13 -pkg-resources==0.0.0  
14 pycpfcnpj==1.0.2 13 pycpfcnpj==1.0.2
15 six==1.10.0 14 six==1.10.0
16 slugify==0.0.1 15 slugify==0.0.1
users/forms.py
@@ -27,25 +27,6 @@ class ProfileForm(forms.ModelForm): @@ -27,25 +27,6 @@ class ProfileForm(forms.ModelForm):
27 } 27 }
28 28
29 class UserForm(RegisterUserForm): 29 class UserForm(RegisterUserForm):
30 - def save(self, commit=True):  
31 - super(UserForm, self).save()  
32 -  
33 - if not self.instance.image:  
34 - self.instance.image = os.path.join(os.path.dirname(settings.BASE_DIR), 'uploads', 'no_image.jpg')  
35 -  
36 - self.instance.set_password(self.cleaned_data['password1'])  
37 - self.instance.save()  
38 -  
39 - if self.instance.is_staff:  
40 - assign_role(self.instance, 'system_admin')  
41 - elif self.instance.type_profile == 2:  
42 - assign_role(self.instance, 'student')  
43 - elif self.instance.type_profile == 1:  
44 - assign_role(self.instance, 'professor')  
45 -  
46 - self.instance.save()  
47 -  
48 - return self.instance  
49 30
50 class Meta: 31 class Meta:
51 model = User 32 model = User
@@ -59,7 +40,8 @@ class EditUserForm(forms.ModelForm): @@ -59,7 +40,8 @@ class EditUserForm(forms.ModelForm):
59 40
60 # Ailson 41 # Ailson
61 class UpdateUserForm(forms.ModelForm): 42 class UpdateUserForm(forms.ModelForm):
  43 + company_logo = forms.ImageField(label=_('Company Logo'),required=False, error_messages = {'invalid':_("Image files only")})
62 44
63 - class Meta:  
64 - model = User  
65 - fields = ['username', 'name', 'email', 'city', 'state', 'birth_date', 'gender', 'cpf', 'phone', 'image'] 45 + class Meta:
  46 + model = User
  47 + fields = ['username', 'name', 'email', 'city', 'state', 'birth_date', 'gender', 'cpf', 'phone', 'image']
66 \ No newline at end of file 48 \ No newline at end of file
users/templates/list_users.html
@@ -63,9 +63,29 @@ @@ -63,9 +63,29 @@
63 <p>{% trans 'Contact' %}: {{ acc.phone }}</p> 63 <p>{% trans 'Contact' %}: {{ acc.phone }}</p>
64 <div align="right"> 64 <div align="right">
65 <a href="{% url 'users:update' acc.username %}" class="btn btn-raised btn-success">{% trans 'Edit' %}</a> 65 <a href="{% url 'users:update' acc.username %}" class="btn btn-raised btn-success">{% trans 'Edit' %}</a>
66 - <a href="javascript:void(0)" class="btn btn-raised btn-primary">{% trans 'Delete' %}</a> 66 + <a href="javascript:void(0)" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#DeleteModal">{% trans 'Delete' %}</a>
67 </div> 67 </div>
68 </div> 68 </div>
  69 +
  70 +
  71 + <!-- Modal -->
  72 + <div class="modal fade" id="DeleteModal" tabindex="-1" role="dialog" aria-labelledby="DeleteModalLabel">
  73 + <div class="modal-dialog" role="document">
  74 + <div class="modal-content">
  75 + <div class="modal-header">
  76 + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
  77 + <h4 class="modal-title" id="DeleteModalLabel">Confirm delete</h4>
  78 + </div>
  79 + <div class="modal-body">
  80 + Are you sure you want to delete?
  81 + </div>
  82 + <div class="modal-footer">
  83 + <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
  84 + <button type="button" class="btn btn-primary">Delete</button>
  85 + </div>
  86 + </div>
  87 + </div>
  88 + </div>
69 </div> 89 </div>
70 </div> 90 </div>
71 {% endfor %} 91 {% endfor %}
users/templates/users/create.html
@@ -33,10 +33,18 @@ @@ -33,10 +33,18 @@
33 {% for field in form %} 33 {% for field in form %}
34 <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput"> 34 <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput">
35 {% if field.auto_id == 'id_birth_date' %} 35 {% if field.auto_id == 'id_birth_date' %}
36 - <label for="{{ field.auto_id }}">{{ field.label }}</label> 36 + {% if field.field.required %}
  37 + <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label>
  38 + {% else %}
  39 + <label for="{{ field.auto_id }}">{{ field.label }}</label>
  40 + {% endif %}
37 <input type="date" class="form-control"name="{{field.name}}" value="{% if field.value.year %}{{field.value|date:'Y-m-d'}}{% else %}{{field.value}}{% endif %}"> 41 <input type="date" class="form-control"name="{{field.name}}" value="{% if field.value.year %}{{field.value|date:'Y-m-d'}}{% else %}{{field.value}}{% endif %}">
38 {% elif field.auto_id == 'id_image' %} 42 {% elif field.auto_id == 'id_image' %}
39 - <label for="{{ field.auto_id }}">{{ field.label }}</label> 43 + {% if field.field.required %}
  44 + <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label>
  45 + {% else %}
  46 + <label for="{{ field.auto_id }}">{{ field.label }}</label>
  47 + {% endif %}
40 {% render_field field class='form-control' %} 48 {% render_field field class='form-control' %}
41 <div class="input-group"> 49 <div class="input-group">
42 <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your photo...' %}"> 50 <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your photo...' %}">
@@ -53,15 +61,23 @@ @@ -53,15 +61,23 @@
53 </label> 61 </label>
54 </div> 62 </div>
55 {% elif field.auto_id == 'id_cpf' %} 63 {% elif field.auto_id == 'id_cpf' %}
56 - <label for="{{ field.auto_id }}">{{ field.label }}</label> 64 + {% if field.field.required %}
  65 + <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label>
  66 + {% else %}
  67 + <label for="{{ field.auto_id }}">{{ field.label }}</label>
  68 + {% endif %}
57 {% render_field field class='form-control' onkeypress='campoNumerico(this,event); formatarCpf(this,event);' %} 69 {% render_field field class='form-control' onkeypress='campoNumerico(this,event); formatarCpf(this,event);' %}
58 {% else %} 70 {% else %}
59 - <label for="{{ field.auto_id }}">{{ field.label }}</label> 71 + {% if field.field.required %}
  72 + <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label>
  73 + {% else %}
  74 + <label for="{{ field.auto_id }}">{{ field.label }}</label>
  75 + {% endif %}
60 {% render_field field class='form-control' %} 76 {% render_field field class='form-control' %}
61 {% endif %} 77 {% endif %}
62 <span id="helpBlock" class="help-block">{{ field.help_text }}</span> 78 <span id="helpBlock" class="help-block">{{ field.help_text }}</span>
63 - {% if field.errors.length > 0 %}  
64 - <div class="alert alert-danger alert-dismissible" role="alert"> 79 + {% if field.errors %}
  80 + <div class="alert alert-danger alert-dismissible col-md-offset-4 col-md-8" role="alert">
65 <button type="button" class="close" data-dismiss="alert" aria-label="Close"> 81 <button type="button" class="close" data-dismiss="alert" aria-label="Close">
66 <span aria-hidden="true">&times;</span> 82 <span aria-hidden="true">&times;</span>
67 </button> 83 </button>
users/templates/users/profile.html
@@ -28,10 +28,8 @@ @@ -28,10 +28,8 @@
28 28
29 {% block content %} 29 {% block content %}
30 <div class="row"> 30 <div class="row">
31 - <div class="row">  
32 - <div class="col-lg-offset-4 col-lg-2">  
33 - <img src="" class="img-responsive center-block " alt="logo amadeus">  
34 - </div> 31 + <div class="col-lg-offset-4 col-lg-2">
  32 + <img src="" class="img-responsive center-block " alt="logo amadeus">
35 </div> 33 </div>
36 </div> 34 </div>
37 <div class="row"> 35 <div class="row">
users/templates/users/update.html
@@ -46,18 +46,14 @@ @@ -46,18 +46,14 @@
46 </button> 46 </button>
47 </span> 47 </span>
48 </div> 48 </div>
49 - {% elif field.auto_id == 'id_is_staff' or field.auto_id == 'id_is_active' %}  
50 - <div class="checkbox">  
51 - <label>  
52 - {% render_field field type='checkbox' %}  
53 - </label>  
54 - </div> 49 + {% elif field.auto_id == 'id_cpf' %}
  50 + {% render_field field class='form-control' onkeypress='campoNumerico(this,event); formatarCpf(this,event);' %}
55 {% else %} 51 {% else %}
56 {% render_field field class='form-control' %} 52 {% render_field field class='form-control' %}
57 <span id="helpBlock" class="help-block">{{ field.help_text }}</span> 53 <span id="helpBlock" class="help-block">{{ field.help_text }}</span>
58 {% endif %} 54 {% endif %}
59 - {% if field.errors.length > 0 %}  
60 - <div class="alert alert-danger alert-dismissible" role="alert"> 55 + {% if field.errors %}
  56 + <div class="alert alert-danger alert-dismissible col-md-offset-4 col-md-8" role="alert">
61 <button type="button" class="close" data-dismiss="alert" aria-label="Close"> 57 <button type="button" class="close" data-dismiss="alert" aria-label="Close">
62 <span aria-hidden="true">&times;</span> 58 <span aria-hidden="true">&times;</span>
63 </button> 59 </button>
@@ -67,7 +63,6 @@ @@ -67,7 +63,6 @@
67 {% endfor %} 63 {% endfor %}
68 </ul> 64 </ul>
69 </div> 65 </div>
70 - </div>  
71 {% endif %} 66 {% endif %}
72 </div> 67 </div>
73 {% endfor %} 68 {% endfor %}
users/views.py
@@ -10,6 +10,7 @@ from rolepermissions.shortcuts import assign_role @@ -10,6 +10,7 @@ from rolepermissions.shortcuts import assign_role
10 from .models import User 10 from .models import User
11 from .forms import UserForm, ProfileForm, UpdateUserForm 11 from .forms import UserForm, ProfileForm, UpdateUserForm
12 12
  13 +# ================ ADMIN =======================
13 class UsersListView(HasRoleMixin, LoginRequiredMixin, generic.ListView): 14 class UsersListView(HasRoleMixin, LoginRequiredMixin, generic.ListView):
14 15
15 allowed_roles = ['system_admin'] 16 allowed_roles = ['system_admin']
@@ -65,7 +66,7 @@ class Update(HasRoleMixin, LoginRequiredMixin, generic.UpdateView): @@ -65,7 +66,7 @@ class Update(HasRoleMixin, LoginRequiredMixin, generic.UpdateView):
65 slug_url_kwarg = 'username' 66 slug_url_kwarg = 'username'
66 context_object_name = 'acc' 67 context_object_name = 'acc'
67 model = User 68 model = User
68 - form_class = UserForm 69 + form_class = UpdateUserForm
69 success_url = reverse_lazy('users:manage') 70 success_url = reverse_lazy('users:manage')
70 71
71 def form_valid(self, form): 72 def form_valid(self, form):
@@ -94,6 +95,36 @@ class View(LoginRequiredMixin, generic.DetailView): @@ -94,6 +95,36 @@ class View(LoginRequiredMixin, generic.DetailView):
94 slug_field = 'username' 95 slug_field = 'username'
95 slug_url_kwarg = 'username' 96 slug_url_kwarg = 'username'
96 97
  98 +class UpdateUser(LoginRequiredMixin, generic.edit.UpdateView):
  99 +
  100 + allowed_roles = ['student']
  101 + login_url = reverse_lazy("core:home")
  102 + template_name = 'users/edit_profile.html'
  103 + form_class = UpdateUserForm
  104 + success_url = reverse_lazy('users:update_profile')
  105 +
  106 + def get_object(self):
  107 + user = get_object_or_404(User, username = self.request.user.username)
  108 + return user
  109 +
  110 + def form_valid(self, form):
  111 + form.save()
  112 + messages.success(self.request, _('Profile edited successfully!'))
  113 +
  114 + return super(UpdateUser, self).form_valid(form)
  115 +
  116 +class DeleteUser(LoginRequiredMixin, generic.edit.DeleteView):
  117 + allowed_roles = ['student']
  118 + login_url = reverse_lazy("core:home")
  119 + model = User
  120 + success_url = reverse_lazy('core:index')
  121 + success_message = "Deleted Successfully"
  122 +
  123 + def get_queryset(self):
  124 + user = get_object_or_404(User, username = self.request.user.username)
  125 + return user
  126 +
  127 +
97 class Profile(LoginRequiredMixin, generic.DetailView): 128 class Profile(LoginRequiredMixin, generic.DetailView):
98 129
99 login_url = reverse_lazy("core:home") 130 login_url = reverse_lazy("core:home")
@@ -131,34 +162,4 @@ class EditProfile(LoginRequiredMixin, generic.UpdateView): @@ -131,34 +162,4 @@ class EditProfile(LoginRequiredMixin, generic.UpdateView):
131 162
132 messages.success(self.request, _('Profile edited successfully!')) 163 messages.success(self.request, _('Profile edited successfully!'))
133 164
134 - return super(EditProfile, self).form_valid(form)  
135 -  
136 -  
137 -class UpdateUser(LoginRequiredMixin, generic.edit.UpdateView):  
138 -  
139 - allowed_roles = ['student']  
140 - login_url = reverse_lazy("core:home")  
141 - template_name = 'users/edit_profile.html'  
142 - form_class = UpdateUserForm  
143 - success_url = reverse_lazy('users:update_profile')  
144 -  
145 - def get_object(self):  
146 - user = get_object_or_404(User, username = self.request.user.username)  
147 - return user  
148 -  
149 - def form_valid(self, form):  
150 - form.save()  
151 - messages.success(self.request, _('Profile edited successfully!'))  
152 -  
153 - return super(UpdateUser, self).form_valid(form)  
154 -  
155 -class DeleteUser(LoginRequiredMixin, generic.edit.DeleteView):  
156 - allowed_roles = ['student']  
157 - login_url = reverse_lazy("core:home")  
158 - model = User  
159 - success_url = reverse_lazy('core:index')  
160 - success_message = "Deleted Successfully"  
161 -  
162 - def get_queryset(self):  
163 - user = get_object_or_404(User, username = self.request.user.username)  
164 - return user 165 + return super(EditProfile, self).form_valid(form)
165 \ No newline at end of file 166 \ No newline at end of file