Commit f0c5784dcec874d8bcf462de22567f828e2062ca
Exists in
master
and in
5 other branches
Merge branch 'dev' of https://github.com/amadeusproject/amadeuslms into dev
Showing
49 changed files
with
612 additions
and
446 deletions
Show diff stats
amadeus/settings.py
core/context_processors.py
... | ... | @@ -5,6 +5,6 @@ def notifications(request): |
5 | 5 | context['notifications'] = None |
6 | 6 | if request.user.is_authenticated: |
7 | 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 | 10 | return context | ... | ... |
core/forms.py
... | ... | @@ -15,31 +15,7 @@ class RegisterUserForm(forms.ModelForm): |
15 | 15 | |
16 | 16 | def validate_cpf(self, cpf): |
17 | 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 | 19 | if cpfcnpj.validate(cpf): |
44 | 20 | return True |
45 | 21 | return False | ... | ... |
core/static/css/base/amadeus.css
core/static/js/base/amadeus.js
... | ... | @@ -126,4 +126,14 @@ function validarCpfSemAlert(campo,nome,idElementoMensagemErro){ |
126 | 126 | return true; |
127 | 127 | } |
128 | 128 | return retorno; |
129 | -} | |
130 | 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 | 1 | $(document).ready(function(){ |
2 | 2 | $('[data-toggle="tooltip"]').tooltip(); //activate tooltip on all elements that has attribute data-toggle |
3 | -}); | |
4 | 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 | 27 | \ No newline at end of file | ... | ... |
core/templates/base.html
... | ... | @@ -8,7 +8,7 @@ |
8 | 8 | |
9 | 9 | <meta http-equiv="Cache-Control" content="no-cache, no-store" /> |
10 | 10 | <link href="{% static 'img/favicon.ico' %}" rel="shortcut icon" /> |
11 | - | |
11 | + | |
12 | 12 | <!-- Roboto font --> |
13 | 13 | <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:300,400,500,700" type="text/css"> |
14 | 14 | <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> |
... | ... | @@ -18,11 +18,11 @@ |
18 | 18 | <script type="text/javascript" src="{% static 'js/vendor/jquery-ui.js' %}"></script> |
19 | 19 | |
20 | 20 | <!-- Bootstrap and themes (material) --> |
21 | - <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/bootstrap.min.css' %}"> | |
21 | + <link rel="stylesheet" type="text/css" href="{% static 'bootstrap-3.3.7/css/bootstrap.css' %}"> | |
22 | 22 | <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/material.min.css' %}"> |
23 | 23 | <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/ripples.min.css' %}"> |
24 | - <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/datepicker.css' %}"> | |
25 | - <script type="text/javascript" src="{% static 'js/vendor/bootstrap.min.js' %}"></script> | |
24 | + <link rel="stylesheet" type="text/css" href="{% static 'css/datepicker.css' %}"> | |
25 | + <script type="text/javascript" src="{% static 'bootstrap-3.3.7/js/bootstrap.js' %}"></script> | |
26 | 26 | <script type="text/javascript" src="{% static 'js/vendor/bootstrap-acessibility.min.js' %}"></script> |
27 | 27 | <script type="text/javascript" src="{% static 'js/vendor/material.min.js' %}"></script> |
28 | 28 | <script type="text/javascript" src="{% static 'js/vendor/ripples.min.js' %}"></script> |
... | ... | @@ -38,6 +38,7 @@ |
38 | 38 | <script type="text/javascript">$.material.init()</script> |
39 | 39 | |
40 | 40 | <!--Javascript block for specific-app ones --> |
41 | + <script src="{% static 'js/base/amadeus.js' %}"></script> | |
41 | 42 | {% block style %} |
42 | 43 | {% endblock %} |
43 | 44 | </head> |
... | ... | @@ -60,40 +61,10 @@ |
60 | 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 | 62 | <ul id="notification-dropdown" class="dropdown-menu"> |
62 | 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 | 66 | <li> |
96 | - <a> | |
67 | + <a onclick="getNotifications(5)"> | |
97 | 68 | <div class="list-group-item"> |
98 | 69 | <div class="row-content"> |
99 | 70 | <p class="list-group-item-text">See More</p> |
... | ... | @@ -141,8 +112,6 @@ |
141 | 112 | </div> |
142 | 113 | </div> |
143 | 114 | </div> |
144 | - | |
145 | - | |
146 | 115 | </div> |
147 | 116 | </div> |
148 | 117 | </body> | ... | ... |
... | ... | @@ -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 | 32 | \ No newline at end of file | ... | ... |
core/templates/register_user.html
... | ... | @@ -8,11 +8,16 @@ |
8 | 8 | |
9 | 9 | |
10 | 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">×</span> | |
16 | + </button> | |
17 | + <p>{{ message }}</p> | |
18 | + </div> | |
19 | + {% endfor %} | |
20 | + {% endif %} | |
16 | 21 | <div class="row logo-row"> |
17 | 22 | <div class="col-lg-offset-2 col-lg-9"> |
18 | 23 | <img src="{% static 'img/amadeus.png' %}" class="img-responsive center-block " alt="logo amadeus" id="logo"> |
... | ... | @@ -29,7 +34,11 @@ |
29 | 34 | <legend>{% trans 'User Register' %}</legend> |
30 | 35 | {% for field in form %} |
31 | 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 | 42 | <div class="col-md-8"> |
34 | 43 | {% if field.auto_id == 'id_birth_date' %} |
35 | 44 | {% render_field field class='form-control input-sm' type='date' %} |
... | ... | @@ -81,5 +90,4 @@ |
81 | 90 | </div> |
82 | 91 | |
83 | 92 | <br clear="all" /> |
84 | - <script src="{% static 'js/base/amadeus.js' %}"></script> | |
85 | 93 | {% endblock %} | ... | ... |
core/tests.py
... | ... | @@ -89,7 +89,7 @@ class RegisterUserTestCase(TestCase): |
89 | 89 | } |
90 | 90 | |
91 | 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 | 94 | data = { |
95 | 95 | 'username': '', |
... | ... | @@ -102,7 +102,7 @@ class RegisterUserTestCase(TestCase): |
102 | 102 | 'gender': 'F', |
103 | 103 | } |
104 | 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 | 107 | class RememberPasswordTestCase(TestCase): |
108 | 108 | |
... | ... | @@ -194,7 +194,7 @@ class UpdateUserTestCase(TestCase): |
194 | 194 | 'gender': 'F', |
195 | 195 | } |
196 | 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 | 200 | class DeleteUserTestCase(TestCase): | ... | ... |
core/urls.py
... | ... | @@ -9,5 +9,6 @@ urlpatterns = [ |
9 | 9 | url(r'^register/$', views.RegisterUser.as_view(), name='register'), |
10 | 10 | url(r'^remember_password/$', views.remember_password, name='remember_password'), |
11 | 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 | ] | ... | ... |
core/views.py
... | ... | @@ -5,8 +5,9 @@ from django.contrib.auth.mixins import LoginRequiredMixin |
5 | 5 | from .decorators import log_decorator |
6 | 6 | from django.contrib import messages |
7 | 7 | from django.shortcuts import render, redirect |
8 | +from django.template.loader import render_to_string | |
8 | 9 | from django.views.generic import CreateView, UpdateView |
9 | -from django.http import HttpResponse | |
10 | +from django.http import HttpResponse, JsonResponse | |
10 | 11 | from django.core.mail import send_mail,BadHeaderError |
11 | 12 | from django.conf import settings |
12 | 13 | from core.mixins import NotificationMixin |
... | ... | @@ -95,6 +96,28 @@ def processNotification(self, notificationId): |
95 | 96 | notification.save() |
96 | 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 | 121 | # class LoginClass(LoginView): |
99 | 122 | # template_name='index.html' |
100 | 123 | # | ... | ... |
courses/migrations/0001_initial.py
1 | 1 | # -*- coding: utf-8 -*- |
2 | -# Generated by Django 1.10 on 2016-09-22 05:46 | |
2 | +# Generated by Django 1.10 on 2016-09-28 20:27 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | 5 | import autoslug.fields |
... | ... | @@ -22,7 +22,6 @@ class Migration(migrations.Migration): |
22 | 22 | name='Activity', |
23 | 23 | fields=[ |
24 | 24 | ('resource_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.Resource')), |
25 | - ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), | |
26 | 25 | ('limit_date', models.DateTimeField(verbose_name='Deliver Date')), |
27 | 26 | ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='student')), |
28 | 27 | ], |
... | ... | @@ -37,8 +36,8 @@ class Migration(migrations.Migration): |
37 | 36 | ('create_date', models.DateField(auto_now_add=True, verbose_name='Creation Date')), |
38 | 37 | ], |
39 | 38 | options={ |
40 | - 'verbose_name_plural': 'Categories', | |
41 | 39 | 'verbose_name': 'Category', |
40 | + 'verbose_name_plural': 'Categories', | |
42 | 41 | }, |
43 | 42 | ), |
44 | 43 | migrations.CreateModel( |
... | ... | @@ -57,20 +56,19 @@ class Migration(migrations.Migration): |
57 | 56 | ('end_date', models.DateField(verbose_name='End of Course Date')), |
58 | 57 | ('image', models.ImageField(blank=True, upload_to='courses/', verbose_name='Image')), |
59 | 58 | ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Category', verbose_name='Category')), |
60 | - ('professors', models.ManyToManyField(related_name='courses', to=settings.AUTH_USER_MODEL, verbose_name='Professors')), | |
59 | + ('professors', models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors')), | |
61 | 60 | ('students', models.ManyToManyField(related_name='courses_student', to=settings.AUTH_USER_MODEL, verbose_name='Students')), |
62 | 61 | ], |
63 | 62 | options={ |
63 | + 'verbose_name': 'Course', | |
64 | 64 | 'verbose_name_plural': 'Courses', |
65 | 65 | 'ordering': ('create_date', 'name'), |
66 | - 'verbose_name': 'Course', | |
67 | 66 | }, |
68 | 67 | ), |
69 | 68 | migrations.CreateModel( |
70 | 69 | name='Material', |
71 | 70 | fields=[ |
72 | 71 | ('resource_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.Resource')), |
73 | - ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), | |
74 | 72 | ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='student')), |
75 | 73 | ], |
76 | 74 | bases=('core.resource',), |
... | ... | @@ -91,9 +89,23 @@ class Migration(migrations.Migration): |
91 | 89 | ('professors', models.ManyToManyField(related_name='subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors')), |
92 | 90 | ], |
93 | 91 | options={ |
92 | + 'verbose_name': 'Subject', | |
94 | 93 | 'verbose_name_plural': 'Subjects', |
95 | 94 | 'ordering': ('create_date', 'name'), |
96 | - 'verbose_name': 'Subject', | |
95 | + }, | |
96 | + ), | |
97 | + migrations.CreateModel( | |
98 | + name='SubjectCategory', | |
99 | + fields=[ | |
100 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
101 | + ('name', models.CharField(max_length=100, verbose_name='Name')), | |
102 | + ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')), | |
103 | + ('description', models.TextField(blank=True, verbose_name='Description')), | |
104 | + ('subjects', models.ManyToManyField(to='courses.Subject')), | |
105 | + ], | |
106 | + options={ | |
107 | + 'verbose_name': 'subject category', | |
108 | + 'verbose_name_plural': 'subject categories', | |
97 | 109 | }, |
98 | 110 | ), |
99 | 111 | migrations.CreateModel( |
... | ... | @@ -110,9 +122,9 @@ class Migration(migrations.Migration): |
110 | 122 | ('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Subject', verbose_name='Subject')), |
111 | 123 | ], |
112 | 124 | options={ |
125 | + 'verbose_name': 'Topic', | |
113 | 126 | 'verbose_name_plural': 'Topics', |
114 | 127 | 'ordering': ('create_date', 'name'), |
115 | - 'verbose_name': 'Topic', | |
116 | 128 | }, |
117 | 129 | ), |
118 | 130 | migrations.AddField( | ... | ... |
courses/migrations/0002_auto_20160926_0026.py
... | ... | @@ -1,38 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-09-26 03:26 | |
3 | -from __future__ import unicode_literals | |
4 | - | |
5 | -import autoslug.fields | |
6 | -from django.db import migrations, models | |
7 | - | |
8 | - | |
9 | -class Migration(migrations.Migration): | |
10 | - | |
11 | - dependencies = [ | |
12 | - ('courses', '0001_initial'), | |
13 | - ] | |
14 | - | |
15 | - operations = [ | |
16 | - migrations.CreateModel( | |
17 | - name='SubjectCategory', | |
18 | - fields=[ | |
19 | - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
20 | - ('name', models.CharField(max_length=100, verbose_name='Name')), | |
21 | - ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')), | |
22 | - ('description', models.TextField(blank=True, verbose_name='Description')), | |
23 | - ('subjects', models.ManyToManyField(to='courses.Subject')), | |
24 | - ], | |
25 | - options={ | |
26 | - 'verbose_name_plural': 'subject categories', | |
27 | - 'verbose_name': 'subject category', | |
28 | - }, | |
29 | - ), | |
30 | - migrations.RemoveField( | |
31 | - model_name='activity', | |
32 | - name='create_date', | |
33 | - ), | |
34 | - migrations.RemoveField( | |
35 | - model_name='material', | |
36 | - name='create_date', | |
37 | - ), | |
38 | - ] |
courses/migrations/0003_auto_20160927_1945.py
... | ... | @@ -1,52 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-09-27 22:45 | |
3 | -from __future__ import unicode_literals | |
4 | - | |
5 | -from django.conf import settings | |
6 | -from django.db import migrations, models | |
7 | -import django.db.models.deletion | |
8 | - | |
9 | - | |
10 | -class Migration(migrations.Migration): | |
11 | - | |
12 | - dependencies = [ | |
13 | - ('courses', '0002_auto_20160926_0026'), | |
14 | - ] | |
15 | - | |
16 | - operations = [ | |
17 | - migrations.CreateModel( | |
18 | - name='Answer', | |
19 | - fields=[ | |
20 | - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
21 | - ('answer', models.CharField(max_length=200, verbose_name='Answer')), | |
22 | - ('order', models.PositiveSmallIntegerField(verbose_name='Order')), | |
23 | - ], | |
24 | - options={ | |
25 | - 'verbose_name_plural': 'Answers', | |
26 | - 'verbose_name': 'Answer', | |
27 | - 'ordering': ('order',), | |
28 | - }, | |
29 | - ), | |
30 | - migrations.CreateModel( | |
31 | - name='Poll', | |
32 | - fields=[ | |
33 | - ('activity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Activity')), | |
34 | - ('question', models.CharField(max_length=300, verbose_name='Question')), | |
35 | - ], | |
36 | - options={ | |
37 | - 'verbose_name_plural': 'Polls', | |
38 | - 'verbose_name': 'Poll', | |
39 | - }, | |
40 | - bases=('courses.activity',), | |
41 | - ), | |
42 | - migrations.AlterField( | |
43 | - model_name='course', | |
44 | - name='professors', | |
45 | - field=models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors'), | |
46 | - ), | |
47 | - migrations.AddField( | |
48 | - model_name='answer', | |
49 | - name='poll', | |
50 | - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='courses.Poll', verbose_name='Answers'), | |
51 | - ), | |
52 | - ] |
courses/models.py
... | ... | @@ -105,35 +105,11 @@ It is a category for each subject. |
105 | 105 | """ |
106 | 106 | class SubjectCategory(models.Model): |
107 | 107 | name = models.CharField(_('Name'), max_length= 100) |
108 | - slug = AutoSlugField(_("Slug"),populate_from='name',unique=True) | |
108 | + slug = AutoSlugField(_("Slug"),populate_from='name',unique=True) | |
109 | 109 | description = models.TextField(_('Description'), blank = True) |
110 | 110 | subjects = models.ManyToManyField(Subject) |
111 | 111 | |
112 | 112 | class Meta: |
113 | 113 | verbose_name = _('subject category') |
114 | 114 | verbose_name_plural = _('subject categories') |
115 | - | |
116 | -class Poll(Activity): | |
117 | - question = models.CharField(_('Question'), max_length = 300) | |
118 | - | |
119 | - class Meta: | |
120 | - #ordering = ('create_date','name') | |
121 | - verbose_name = _('Poll') | |
122 | - verbose_name_plural = _('Polls') | |
123 | - | |
124 | - def __str__(self): | |
125 | - return str(self.question) + str("/") + str(self.topic) | |
126 | - | |
127 | -class Answer(models.Model): | |
128 | - answer = models.CharField(_("Answer"), max_length = 200) | |
129 | - order = models.PositiveSmallIntegerField(_("Order")) | |
130 | - poll = models.ForeignKey(Poll, verbose_name = _('Answers'), related_name='answers') | |
131 | - | |
132 | - class Meta: | |
133 | - ordering = ('order',) | |
134 | - verbose_name = _('Answer') | |
135 | - verbose_name_plural = _('Answers') | |
136 | - | |
137 | - def __str__(self): | |
138 | - return str(self.question) + str("/") + str(self.topic) | |
139 | - | |
115 | + | ... | ... |
courses/templates/poll/poll.html
... | ... | @@ -1,53 +0,0 @@ |
1 | -{% extends "topic/index.html" %} | |
2 | - | |
3 | -{% load i18n %} | |
4 | - | |
5 | -{% block style %} | |
6 | - <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> | |
7 | -{% endblock %} | |
8 | - | |
9 | -{% block content %} | |
10 | -<div class="col-md-8 col-md-offset-2"> | |
11 | - <div class="panel panel-primary"> | |
12 | - <div class="panel-heading"> | |
13 | - <h3 class="panel-title"> | |
14 | - <span class="glyphicon glyphicon-hand-right"></span> Question?</h3> | |
15 | - </div> | |
16 | - <div class="container-fluid"> | |
17 | - <form id="form" class="" action="" method="post"> | |
18 | - <div class="row form-group"> | |
19 | - <div class="col-md-1"> | |
20 | - </br> | |
21 | - <label><span class="glyphicon glyphicon-menu-hamburger"></span></label> | |
22 | - </div> | |
23 | - <div class="col-md-10"> | |
24 | - <div class="form-control-md has-success is-empty"> | |
25 | - <input type="text" class="form-control" placeholder="Email address default size"> | |
26 | - <span class="help-block">Please enter a valid email address</span> | |
27 | - </div> | |
28 | - </div> | |
29 | - <div class="col-md-1"> | |
30 | - </br> | |
31 | - <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label> | |
32 | - </div> | |
33 | - </div> | |
34 | - </form> | |
35 | - </br> | |
36 | - </div> | |
37 | - | |
38 | - </div> | |
39 | - <div class="panel-footer text-center"> | |
40 | - <button type="button" id="add" class="btn btn-primary btn-block btn-sm">add</button> | |
41 | - <a href="#" class="small">View Result</a> | |
42 | - </div> | |
43 | - </div> | |
44 | -<script type="text/javascript"> | |
45 | -$( "#form" ).sortable({ | |
46 | - delay: 100, | |
47 | - distance: 5, | |
48 | -}); | |
49 | -$("#add").click(function() { | |
50 | - $("#form").append('<div class="row form-group"><div class="col-md-1"></br><label><span class="glyphicon glyphicon-menu-hamburger"></span></label></div><div class="col-md-10"><div class="form-group-md has-success is-empty"><input type="text" class="form-control" placeholder="Email address default size"><span class="help-block">Please enter a valid email address</span></div></div><div class="col-md-1"></br><label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label></div></br></div>'); | |
51 | -}); | |
52 | -</script> | |
53 | -{% endblock content %} |
courses/templates/subject/form_view_teacher.html
... | ... | @@ -32,16 +32,6 @@ |
32 | 32 | <div class="modal-body"> |
33 | 33 | <section> |
34 | 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 | 35 | </section> |
46 | 36 | </div> |
47 | 37 | <div class="modal-footer"> | ... | ... |
courses/urls.py
1 | -from django.conf.urls import url | |
1 | +from django.conf.urls import url, include | |
2 | 2 | |
3 | 3 | from . import views |
4 | 4 | |
... | ... | @@ -22,6 +22,8 @@ urlpatterns = [ |
22 | 22 | url(r'^topics/update/(?P<slug>[\w_-]+)/$', views.UpdateTopicView.as_view(), name='update_topic'), |
23 | 23 | url(r'^topics/(?P<slug>[\w_-]+)/$', views.TopicsView.as_view(), name='view_topic'), |
24 | 24 | url(r'^subjects/categories$',views.IndexSubjectCategoryView.as_view(), name='subject_category_index'), |
25 | - url(r'^to/poll/to/$', views.Poll.as_view(), name='poll'), | |
25 | + | |
26 | + | |
27 | + url(r'^poll/', include('poll.urls', namespace = 'poll')) | |
26 | 28 | |
27 | 29 | ] | ... | ... |
courses/views.py
... | ... | @@ -455,27 +455,3 @@ class IndexSubjectCategoryView(LoginRequiredMixin, generic.ListView): |
455 | 455 | context = super(IndexSubjectCategoryView, self).get_context_data(**kwargs) |
456 | 456 | context['subject_categories'] = SubjectCategory.objects.all() |
457 | 457 | return context |
458 | - | |
459 | - | |
460 | -class Poll(generic.TemplateView): | |
461 | - | |
462 | - # login_url = reverse_lazy("core:home") | |
463 | - # redirect_field_name = 'next' | |
464 | - # model = Course | |
465 | - # context_object_name = 'course' | |
466 | - template_name = 'poll/poll.html' | |
467 | - # queryset = Course.objects.all() | |
468 | - | |
469 | - # def get_queryset(self): | |
470 | - # return Course.objects.all()[0] | |
471 | - | |
472 | - def get_context_data(self, **kwargs): | |
473 | - context = super(Poll, self).get_context_data(**kwargs) | |
474 | - course = Course.objects.all()[0] | |
475 | - context['course'] = course | |
476 | - context['subject'] = course.subjects.all()[0] | |
477 | - context['subjects'] = course.subjects.all() | |
478 | - # if (has_role(self.request.user,'system_admin')): | |
479 | - # context['subjects'] = self.object.course.subjects.all() | |
480 | - return context | |
481 | - | ... | ... |
forum/forms.py
1 | 1 | from django import forms |
2 | 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 | 5 | class ForumForm(forms.ModelForm): |
6 | 6 | |
... | ... | @@ -19,6 +19,19 @@ class ForumForm(forms.ModelForm): |
19 | 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 | 35 | class PostAnswerForm(forms.ModelForm): |
23 | 36 | |
24 | 37 | class Meta: | ... | ... |
forum/migrations/0001_initial.py
1 | 1 | # -*- coding: utf-8 -*- |
2 | -# Generated by Django 1.10 on 2016-09-22 20:41 | |
2 | +# Generated by Django 1.10 on 2016-09-28 20:27 | |
3 | 3 | from __future__ import unicode_literals |
4 | 4 | |
5 | 5 | from django.conf import settings |
... | ... | @@ -21,8 +21,9 @@ class Migration(migrations.Migration): |
21 | 21 | name='Forum', |
22 | 22 | fields=[ |
23 | 23 | ('activity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Activity')), |
24 | - ('title', models.CharField(max_length=100, verbose_name='Title')), | |
25 | 24 | ('description', models.TextField(blank=True, verbose_name='Description')), |
25 | + ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')), | |
26 | + ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Create Date')), | |
26 | 27 | ], |
27 | 28 | options={ |
28 | 29 | 'verbose_name': 'Forum', |
... | ... | @@ -35,6 +36,7 @@ class Migration(migrations.Migration): |
35 | 36 | fields=[ |
36 | 37 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
37 | 38 | ('message', models.TextField(verbose_name='Post message')), |
39 | + ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')), | |
38 | 40 | ('post_date', models.DateTimeField(auto_now_add=True, verbose_name='Post Date')), |
39 | 41 | ('forum', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Forum', verbose_name='Forum')), |
40 | 42 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor')), |
... | ... | @@ -49,6 +51,7 @@ class Migration(migrations.Migration): |
49 | 51 | fields=[ |
50 | 52 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
51 | 53 | ('message', models.TextField(verbose_name='Answer message')), |
54 | + ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')), | |
52 | 55 | ('answer_date', models.DateTimeField(auto_now_add=True, verbose_name='Answer Date')), |
53 | 56 | ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Post', verbose_name='Post')), |
54 | 57 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor')), | ... | ... |
forum/migrations/0002_remove_forum_title.py
... | ... | @@ -1,19 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-09-22 20:43 | |
3 | -from __future__ import unicode_literals | |
4 | - | |
5 | -from django.db import migrations | |
6 | - | |
7 | - | |
8 | -class Migration(migrations.Migration): | |
9 | - | |
10 | - dependencies = [ | |
11 | - ('forum', '0001_initial'), | |
12 | - ] | |
13 | - | |
14 | - operations = [ | |
15 | - migrations.RemoveField( | |
16 | - model_name='forum', | |
17 | - name='title', | |
18 | - ), | |
19 | - ] |
forum/migrations/0003_forum_create_date.py
... | ... | @@ -1,22 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-09-28 02:17 | |
3 | -from __future__ import unicode_literals | |
4 | - | |
5 | -from django.db import migrations, models | |
6 | -import django.utils.timezone | |
7 | - | |
8 | - | |
9 | -class Migration(migrations.Migration): | |
10 | - | |
11 | - dependencies = [ | |
12 | - ('forum', '0002_remove_forum_title'), | |
13 | - ] | |
14 | - | |
15 | - operations = [ | |
16 | - migrations.AddField( | |
17 | - model_name='forum', | |
18 | - name='create_date', | |
19 | - field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now, verbose_name='Create Date'), | |
20 | - preserve_default=False, | |
21 | - ), | |
22 | - ] |
forum/migrations/0004_auto_20160928_1558.py
... | ... | @@ -1,30 +0,0 @@ |
1 | -# -*- coding: utf-8 -*- | |
2 | -# Generated by Django 1.10 on 2016-09-28 18:58 | |
3 | -from __future__ import unicode_literals | |
4 | - | |
5 | -from django.db import migrations, models | |
6 | - | |
7 | - | |
8 | -class Migration(migrations.Migration): | |
9 | - | |
10 | - dependencies = [ | |
11 | - ('forum', '0003_forum_create_date'), | |
12 | - ] | |
13 | - | |
14 | - operations = [ | |
15 | - migrations.AddField( | |
16 | - model_name='forum', | |
17 | - name='modification_date', | |
18 | - field=models.DateTimeField(auto_now=True, verbose_name='Modification Date'), | |
19 | - ), | |
20 | - migrations.AddField( | |
21 | - model_name='post', | |
22 | - name='modification_date', | |
23 | - field=models.DateTimeField(auto_now=True, verbose_name='Modification Date'), | |
24 | - ), | |
25 | - migrations.AddField( | |
26 | - model_name='postanswer', | |
27 | - name='modification_date', | |
28 | - field=models.DateTimeField(auto_now=True, verbose_name='Modification Date'), | |
29 | - ), | |
30 | - ] |
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 | 20 | * Function to load forum to modal |
... | ... | @@ -9,12 +26,45 @@ function showForum(url, forum_id) { |
9 | 26 | data: {'forum_id': forum_id}, |
10 | 27 | success: function(data) { |
11 | 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 | 50 | $('#forumModal').modal(); |
16 | 51 | } |
17 | 52 | |
53 | +function delete_post(url, post) { | |
54 | + var csrftoken = getCookie('csrftoken'); | |
55 | + | |
56 | + $.ajax({ | |
57 | + method: 'post', | |
58 | + beforeSend: function (request) { | |
59 | + request.setRequestHeader('X-CSRFToken', csrftoken); | |
60 | + }, | |
61 | + url: url, | |
62 | + success: function(data) { | |
63 | + $("#post_"+post).remove(); | |
64 | + } | |
65 | + }); | |
66 | +} | |
67 | + | |
18 | 68 | function answer(id, url) { |
19 | 69 | $.ajax({ |
20 | 70 | url: url, | ... | ... |
forum/templates/forum/forum_list.html
1 | 1 | {% load i18n permission_tags list_post %} |
2 | +{% load widget_tweaks %} | |
2 | 3 | |
3 | 4 | <div class="comments-list"> |
4 | 5 | <div class="section-heading"> |
... | ... | @@ -8,7 +9,45 @@ |
8 | 9 | </div> |
9 | 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">×</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 | 52 | <!--{% if foruns|length > 0 %} |
14 | 53 | {% for forum in foruns %} | ... | ... |
forum/templates/post/post_list.html
... | ... | @@ -11,13 +11,14 @@ |
11 | 11 | <i class="material-icons">reply</i> |
12 | 12 | </a> |
13 | 13 | {% if request.user|has_role:'system_admin' or request.user|has_role:'professor' and request.user == post.user %} |
14 | + {% csrf_token %} | |
14 | 15 | <div class="btn-group icon-more-horiz"> |
15 | 16 | <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
16 | 17 | <i class="material-icons">more_horiz</i> |
17 | 18 | </a> |
18 | 19 | <ul class="dropdown-menu" aria-labelledby="dropdownMenu1"> |
19 | 20 | <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> | |
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 | 22 | </ul> |
22 | 23 | </div> |
23 | 24 | {% endif %} | ... | ... |
... | ... | @@ -0,0 +1,31 @@ |
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:void(0)"><i class="material-icons">create</i> {% trans 'Edit' %}</a></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="card-data"> | |
26 | + <p class="comment-date"><i class="fa fa-clock-o"></i> {{ post.post_date }}</p> | |
27 | + </div> | |
28 | + <p class="comment-text">{{ post.message|linebreaks }}</p> | |
29 | + <div class="answer_post"></div> | |
30 | + </div> | |
31 | +</div> | |
0 | 32 | \ No newline at end of file | ... | ... |
forum/templates/post_answers/post_answer_form.html
forum/urls.py
... | ... | @@ -7,6 +7,10 @@ urlpatterns = [ |
7 | 7 | url(r'^$', views.ForumIndex.as_view(), name='index'), |
8 | 8 | url(r'^create$', views.CreateForumView.as_view(), name='create'), |
9 | 9 | url(r'^posts$', views.PostIndex.as_view(), name='posts'), |
10 | + url(r'^create_post$', views.CreatePostView.as_view(), name='create_post'), | |
11 | + url(r'^render_post/([\w_-]+)/$', views.render_post, name='render_post'), | |
12 | + url(r'^delete_post/(?P<pk>[\w_-]+)/$', views.PostDeleteView.as_view(), name='delete_post'), | |
13 | + url(r'^post_deleted/$', views.post_deleted, name='deleted_post'), | |
10 | 14 | url(r'^post_answers$', views.PostAnswerIndex.as_view(), name='post_answers'), |
11 | 15 | url(r'^reply_post$', views.CreatePostAnswerView.as_view(), name='reply_post'), |
12 | 16 | ] | ... | ... |
forum/views.py
1 | +from django.http import HttpResponse | |
1 | 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 | 4 | from django.utils.translation import ugettext_lazy as _ |
4 | 5 | from django.views import generic |
5 | 6 | from django.contrib.auth.mixins import LoginRequiredMixin |
... | ... | @@ -7,7 +8,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin |
7 | 8 | from .models import Forum, Post, PostAnswer |
8 | 9 | from courses.models import Topic |
9 | 10 | |
10 | -from .forms import ForumForm, PostAnswerForm | |
11 | +from .forms import ForumForm, PostForm, PostAnswerForm | |
11 | 12 | |
12 | 13 | class ForumIndex(LoginRequiredMixin, generic.ListView): |
13 | 14 | login_url = reverse_lazy("core:home") |
... | ... | @@ -20,6 +21,12 @@ class ForumIndex(LoginRequiredMixin, generic.ListView): |
20 | 21 | forum_id = self.request.GET.get('forum_id', 0) |
21 | 22 | |
22 | 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 | 31 | return context |
25 | 32 | |
... | ... | @@ -43,6 +50,44 @@ class PostIndex(LoginRequiredMixin, generic.ListView): |
43 | 50 | |
44 | 51 | return context |
45 | 52 | |
53 | +class CreatePostView(LoginRequiredMixin, generic.edit.CreateView): | |
54 | + login_url = reverse_lazy("core:home") | |
55 | + redirect_field_name = 'next' | |
56 | + | |
57 | + form_class = PostForm | |
58 | + | |
59 | + def form_valid(self, form): | |
60 | + self.object = form.save(commit = False) | |
61 | + self.object.user = self.request.user | |
62 | + | |
63 | + self.object.save() | |
64 | + | |
65 | + return super(CreatePostView, self).form_valid(form) | |
66 | + | |
67 | + def get_success_url(self): | |
68 | + self.success_url = reverse('forum:render_post', args = (self.object.id, )) | |
69 | + | |
70 | + return self.success_url | |
71 | + | |
72 | +def render_post(request, post): | |
73 | + last_post = get_object_or_404(Post, id = post) | |
74 | + | |
75 | + context = {} | |
76 | + context['post'] = last_post | |
77 | + | |
78 | + return render(request, "post/post_render.html", context) | |
79 | + | |
80 | +class PostDeleteView(LoginRequiredMixin, generic.DeleteView): | |
81 | + login_url = reverse_lazy("core:home") | |
82 | + redirect_field_name = 'next' | |
83 | + | |
84 | + model = Post | |
85 | + pk_url_kwarg = 'pk' | |
86 | + success_url = reverse_lazy('forum:deleted_post') | |
87 | + | |
88 | +def post_deleted(request): | |
89 | + return HttpResponse(_("Post deleted successfully.")) | |
90 | + | |
46 | 91 | class PostAnswerIndex(LoginRequiredMixin, generic.ListView): |
47 | 92 | login_url = reverse_lazy("core:home") |
48 | 93 | redirect_field_name = 'next' | ... | ... |
... | ... | @@ -0,0 +1,48 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Generated by Django 1.10 on 2016-09-28 20:27 | |
3 | +from __future__ import unicode_literals | |
4 | + | |
5 | +from django.db import migrations, models | |
6 | +import django.db.models.deletion | |
7 | + | |
8 | + | |
9 | +class Migration(migrations.Migration): | |
10 | + | |
11 | + initial = True | |
12 | + | |
13 | + dependencies = [ | |
14 | + ('courses', '0001_initial'), | |
15 | + ] | |
16 | + | |
17 | + operations = [ | |
18 | + migrations.CreateModel( | |
19 | + name='Answer', | |
20 | + fields=[ | |
21 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
22 | + ('answer', models.CharField(max_length=200, verbose_name='Answer')), | |
23 | + ('order', models.PositiveSmallIntegerField(verbose_name='Order')), | |
24 | + ], | |
25 | + options={ | |
26 | + 'verbose_name': 'Answer', | |
27 | + 'verbose_name_plural': 'Answers', | |
28 | + 'ordering': ('order',), | |
29 | + }, | |
30 | + ), | |
31 | + migrations.CreateModel( | |
32 | + name='Poll', | |
33 | + fields=[ | |
34 | + ('activity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Activity')), | |
35 | + ('question', models.CharField(max_length=300, verbose_name='Question')), | |
36 | + ], | |
37 | + options={ | |
38 | + 'verbose_name': 'Poll', | |
39 | + 'verbose_name_plural': 'Polls', | |
40 | + }, | |
41 | + bases=('courses.activity',), | |
42 | + ), | |
43 | + migrations.AddField( | |
44 | + model_name='answer', | |
45 | + name='poll', | |
46 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='poll.Poll', verbose_name='Answers'), | |
47 | + ), | |
48 | + ] | ... | ... |
... | ... | @@ -0,0 +1,30 @@ |
1 | +from django.utils.translation import ugettext_lazy as _ | |
2 | +from django.db import models | |
3 | +from autoslug.fields import AutoSlugField | |
4 | +from users.models import User | |
5 | +from core.models import Resource | |
6 | +from courses.models import Activity | |
7 | + | |
8 | +class Poll(Activity): | |
9 | + question = models.CharField(_('Question'), max_length = 300) | |
10 | + | |
11 | + class Meta: | |
12 | + #ordering = ('create_date','name') | |
13 | + verbose_name = _('Poll') | |
14 | + verbose_name_plural = _('Polls') | |
15 | + | |
16 | + def __str__(self): | |
17 | + return str(self.question) + str("/") + str(self.topic) | |
18 | + | |
19 | +class Answer(models.Model): | |
20 | + answer = models.CharField(_("Answer"), max_length = 200) | |
21 | + order = models.PositiveSmallIntegerField(_("Order")) | |
22 | + poll = models.ForeignKey(Poll, verbose_name = _('Answers'), related_name='answers') | |
23 | + | |
24 | + class Meta: | |
25 | + ordering = ('order',) | |
26 | + verbose_name = _('Answer') | |
27 | + verbose_name_plural = _('Answers') | |
28 | + | |
29 | + def __str__(self): | |
30 | + return str(self.question) + str("/") + str(self.topic) | ... | ... |
... | ... | @@ -0,0 +1,52 @@ |
1 | +{% extends "topic/index.html" %} | |
2 | + | |
3 | +{% load i18n %} | |
4 | + | |
5 | +{% block style %} | |
6 | + <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> | |
7 | +{% endblock %} | |
8 | + | |
9 | +{% block content %} | |
10 | +<div class="col-md-8 col-md-offset-2"> | |
11 | + <div class="panel panel-primary"> | |
12 | + <div class="panel-heading"> | |
13 | + <h3 class="panel-title"> | |
14 | + <span class="glyphicon glyphicon-hand-right"></span> Question?</h3> | |
15 | + </div> | |
16 | + <div class="container-fluid"> | |
17 | + <form id="form" class="" action="" method="post"> | |
18 | + <div class="row form-group"> | |
19 | + <div class="col-md-1"> | |
20 | + </br> | |
21 | + <label><a href=""><span class="glyphicon glyphicon-move"></span></a></label> | |
22 | + </div> | |
23 | + <div class="col-md-10"> | |
24 | + <div class="form-control-md has-success is-empty"> | |
25 | + <input type="text" class="form-control" placeholder="Email address default size"> | |
26 | + <span class="help-block">{% trans "Possible Answer" %}</span> | |
27 | + </div> | |
28 | + </div> | |
29 | + <div class="col-md-1"> | |
30 | + </br> | |
31 | + <label><a href=""><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></a></label> | |
32 | + </div> | |
33 | + </div> | |
34 | + </form> | |
35 | + </br> | |
36 | + </div> | |
37 | + | |
38 | + </div> | |
39 | + <div class="panel-footer text-center"> | |
40 | + <button type="button" id="add" class="btn btn-primary btn-block btn-sm">add</button> | |
41 | + </div> | |
42 | + </div> | |
43 | +<script type="text/javascript"> | |
44 | +$( "#form" ).sortable({ | |
45 | + delay: 100, | |
46 | + distance: 5, | |
47 | +}); | |
48 | +$("#add").click(function() { | |
49 | + $("#form").append('<div class="row form-group"><div class="col-md-1"></br><label><a href=""><span class="glyphicon glyphicon-move"></span></a></label></div><div class="col-md-10"><div class="form-group-md has-success is-empty"><input type="text" class="form-control" placeholder="Email address default size"><span class="help-block">Please enter a valid email address</span></div></div><div class="col-md-1"></br><label><a href=""><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></a></label></div></br></div>'); | |
50 | +}); | |
51 | +</script> | |
52 | +{% endblock content %} | ... | ... |
... | ... | @@ -0,0 +1,38 @@ |
1 | +from django.shortcuts import render, get_object_or_404, redirect | |
2 | +from django.views import generic | |
3 | +from django.contrib.auth.decorators import login_required | |
4 | +from django.core.paginator import Paginator, EmptyPage | |
5 | +from django.contrib.auth.mixins import LoginRequiredMixin | |
6 | +from rolepermissions.mixins import HasRoleMixin | |
7 | +from django.core.urlresolvers import reverse_lazy | |
8 | +from django.utils.translation import ugettext_lazy as _ | |
9 | +from rolepermissions.verifications import has_role | |
10 | +from rolepermissions.verifications import has_object_permission | |
11 | + | |
12 | +# from .forms import CourseForm, UpdateCourseForm, CategoryForm, SubjectForm,TopicForm | |
13 | +# from .models import Course, Subject, Category,Topic, SubjectCategory | |
14 | +from core.mixins import NotificationMixin | |
15 | +from users.models import User | |
16 | +from courses.models import Course | |
17 | + | |
18 | +class Poll(generic.TemplateView): | |
19 | + | |
20 | + # login_url = reverse_lazy("core:home") | |
21 | + # redirect_field_name = 'next' | |
22 | + # model = Course | |
23 | + # context_object_name = 'course' | |
24 | + template_name = 'poll/poll.html' | |
25 | + # queryset = Course.objects.all() | |
26 | + | |
27 | + # def get_queryset(self): | |
28 | + # return Course.objects.all()[0] | |
29 | + | |
30 | + def get_context_data(self, **kwargs): | |
31 | + context = super(Poll, self).get_context_data(**kwargs) | |
32 | + course = Course.objects.all()[0] | |
33 | + context['course'] = course | |
34 | + context['subject'] = course.subjects.all()[0] | |
35 | + context['subjects'] = course.subjects.all() | |
36 | + # if (has_role(self.request.user,'system_admin')): | |
37 | + # context['subjects'] = self.object.course.subjects.all() | |
38 | + return context | ... | ... |
requirements.txt
users/forms.py
... | ... | @@ -27,25 +27,6 @@ class ProfileForm(forms.ModelForm): |
27 | 27 | } |
28 | 28 | |
29 | 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 | 31 | class Meta: |
51 | 32 | model = User |
... | ... | @@ -59,7 +40,8 @@ class EditUserForm(forms.ModelForm): |
59 | 40 | |
60 | 41 | # Ailson |
61 | 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 | 48 | \ No newline at end of file | ... | ... |
users/templates/list_users.html
... | ... | @@ -63,9 +63,29 @@ |
63 | 63 | <p>{% trans 'Contact' %}: {{ acc.phone }}</p> |
64 | 64 | <div align="right"> |
65 | 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 | 67 | </div> |
68 | 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">×</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 | 89 | </div> |
70 | 90 | </div> |
71 | 91 | {% endfor %} | ... | ... |
users/templates/users/create.html
... | ... | @@ -33,10 +33,18 @@ |
33 | 33 | {% for field in form %} |
34 | 34 | <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput"> |
35 | 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 | 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 | 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 | 48 | {% render_field field class='form-control' %} |
41 | 49 | <div class="input-group"> |
42 | 50 | <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your photo...' %}"> |
... | ... | @@ -53,15 +61,23 @@ |
53 | 61 | </label> |
54 | 62 | </div> |
55 | 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 | 69 | {% render_field field class='form-control' onkeypress='campoNumerico(this,event); formatarCpf(this,event);' %} |
58 | 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 | 76 | {% render_field field class='form-control' %} |
61 | 77 | {% endif %} |
62 | 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 | 81 | <button type="button" class="close" data-dismiss="alert" aria-label="Close"> |
66 | 82 | <span aria-hidden="true">×</span> |
67 | 83 | </button> | ... | ... |
users/templates/users/profile.html
... | ... | @@ -28,10 +28,8 @@ |
28 | 28 | |
29 | 29 | {% block content %} |
30 | 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 | 33 | </div> |
36 | 34 | </div> |
37 | 35 | <div class="row"> | ... | ... |
users/templates/users/update.html
... | ... | @@ -46,18 +46,14 @@ |
46 | 46 | </button> |
47 | 47 | </span> |
48 | 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 | 51 | {% else %} |
56 | 52 | {% render_field field class='form-control' %} |
57 | 53 | <span id="helpBlock" class="help-block">{{ field.help_text }}</span> |
58 | 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 | 57 | <button type="button" class="close" data-dismiss="alert" aria-label="Close"> |
62 | 58 | <span aria-hidden="true">×</span> |
63 | 59 | </button> |
... | ... | @@ -67,7 +63,6 @@ |
67 | 63 | {% endfor %} |
68 | 64 | </ul> |
69 | 65 | </div> |
70 | - </div> | |
71 | 66 | {% endif %} |
72 | 67 | </div> |
73 | 68 | {% endfor %} | ... | ... |
users/views.py
... | ... | @@ -10,6 +10,7 @@ from rolepermissions.shortcuts import assign_role |
10 | 10 | from .models import User |
11 | 11 | from .forms import UserForm, ProfileForm, UpdateUserForm |
12 | 12 | |
13 | +# ================ ADMIN ======================= | |
13 | 14 | class UsersListView(HasRoleMixin, LoginRequiredMixin, generic.ListView): |
14 | 15 | |
15 | 16 | allowed_roles = ['system_admin'] |
... | ... | @@ -65,7 +66,7 @@ class Update(HasRoleMixin, LoginRequiredMixin, generic.UpdateView): |
65 | 66 | slug_url_kwarg = 'username' |
66 | 67 | context_object_name = 'acc' |
67 | 68 | model = User |
68 | - form_class = UserForm | |
69 | + form_class = UpdateUserForm | |
69 | 70 | success_url = reverse_lazy('users:manage') |
70 | 71 | |
71 | 72 | def form_valid(self, form): |
... | ... | @@ -94,6 +95,36 @@ class View(LoginRequiredMixin, generic.DetailView): |
94 | 95 | slug_field = 'username' |
95 | 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 | 128 | class Profile(LoginRequiredMixin, generic.DetailView): |
98 | 129 | |
99 | 130 | login_url = reverse_lazy("core:home") |
... | ... | @@ -131,34 +162,4 @@ class EditProfile(LoginRequiredMixin, generic.UpdateView): |
131 | 162 | |
132 | 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 | 166 | \ No newline at end of file | ... | ... |