Commit 75162f0f48d8599787eb9e048f114444d19b0b48
Exists in
master
and in
5 other branches
fixing conflits
Showing
37 changed files
with
851 additions
and
241 deletions
Show diff stats
amadeus/settings.py
app/templates/app/base.html
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | {% block menu_top %} |
6 | 6 | <ul class="nav navbar-nav"> |
7 | 7 | <li class="active"> |
8 | - <a href="#">Home</a> | |
8 | + <a href="{% url 'home' %}">Home</a> | |
9 | 9 | </li> |
10 | 10 | <li><a href="#contact">{% trans 'The Project' %}</a></li> |
11 | 11 | <li><a href="#contact">{% trans 'CCTE Group' %}</a></li> | ... | ... |
app/templates/home.html
... | ... | @@ -64,7 +64,7 @@ |
64 | 64 | {% block sidebar %} |
65 | 65 | <div class="panel panel-primary"> |
66 | 66 | <div class="panel-heading"> |
67 | - <img src="{{ user.image.url }}" id="img" class="img-rounded"> | |
67 | + <img src="{{ user.image_url }}" id="img" class="img-rounded"> | |
68 | 68 | <p></p> |
69 | 69 | <div class="row"> |
70 | 70 | <div class="col-xs-3 col-md-3"> |
... | ... | @@ -86,14 +86,24 @@ |
86 | 86 | <li> <a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> |
87 | 87 | <li> <a href="{% url 'users:profile' %}">{% trans 'Profile' %}</a></li> |
88 | 88 | <li> <a href="#">{% trans 'Pending Tasks' %}</a></li> |
89 | - {% if user|has_role:'student' %} | |
90 | - <li> <a href="#">{% trans 'My courses' %}</a></li> | |
89 | + {% if user|has_role:'student' and not user.is_staff %} | |
90 | + <li> <a href="{% url 'course:manage' %}">{% trans 'My courses' %}</a></li> | |
91 | 91 | {% endif %} |
92 | 92 | {% if user|has_role:'system_admin' %} |
93 | 93 | <li> <a href="{% url 'users:manage' %}">{% trans 'Manage Users' %}</a></li> |
94 | 94 | {% endif %} |
95 | - {% if user|has_role:'system_admin, professor' %} | |
96 | - <li> <a href="{% url 'course:manage' %}">{% trans 'Manage Courses' %}</a></li> | |
95 | + {% if user|has_role:'system_admin' or user|has_role:'professor' %} | |
96 | + <li> | |
97 | + <a href="#courses_list" class="accordion" data-toggle="collapse">{% trans 'Manage Courses' %}</a> | |
98 | + | |
99 | + <div id="courses_list" class="collapse"> | |
100 | + <ul class="nav nav-pill nav-stacked accordion_list"> | |
101 | + {% for course in courses_list %} | |
102 | + <li><a href="{% url 'course:view' course.slug %}">{{ course }}</a></li> | |
103 | + {% endfor %} | |
104 | + </ul> | |
105 | + </div> | |
106 | + </li> | |
97 | 107 | {% endif %} |
98 | 108 | </ul> |
99 | 109 | </div> | ... | ... |
app/templates/home_student.html
... | ... | @@ -23,7 +23,7 @@ |
23 | 23 | <div class="panel-body"> |
24 | 24 | <ul class="nav nav-pills nav-stacked"> |
25 | 25 | <li><a href="{% url 'users:profile' %}">{% trans 'Profile' %}</a></li> |
26 | - <li><a href="javascript:void(0)">{% trans 'My Courses' %}</a></li> | |
26 | + <li><a href="{% url 'course:manage' %}">{% trans 'My Courses' %}</a></li> | |
27 | 27 | <li><a href="javascript:void(0)">{% trans 'Google accounts' %}</a></li> |
28 | 28 | </ul> |
29 | 29 | </div> | ... | ... |
app/templates/home_teacher_student_content.html
1 | -{% load i18n %} | |
1 | +{% load static i18n %} | |
2 | 2 | |
3 | 3 | {% for notification in objects %} |
4 | 4 | <li {% if not notification.read %}class="not_read"{% endif %}> |
5 | 5 | <div class="avatar"> |
6 | - <img src="{{ notification.user.image.url }}"> | |
6 | + <img src="{{ notification.user.image_url }}"> | |
7 | 7 | </div> |
8 | 8 | <div class="bubble-container"> |
9 | 9 | <div class="bubble"> | ... | ... |
app/views.py
... | ... | @@ -43,8 +43,7 @@ class AppIndex(LoginRequiredMixin, LogMixin, ListView, NotificationMixin): |
43 | 43 | else: |
44 | 44 | self.template_name = "home_teacher_student_content.html" |
45 | 45 | |
46 | - | |
47 | - super(AppIndex, self).createNotification("teste", not_resource="home", resource_link="/register") | |
46 | + | |
48 | 47 | return self.response_class(request = self.request, template = self.template_name, context = context, using = self.template_engine, **response_kwargs) |
49 | 48 | |
50 | 49 | ... | ... |
... | ... | @@ -0,0 +1,20 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Generated by Django 1.10 on 2016-09-16 04:26 | |
3 | +from __future__ import unicode_literals | |
4 | + | |
5 | +from django.db import migrations | |
6 | + | |
7 | + | |
8 | +class Migration(migrations.Migration): | |
9 | + | |
10 | + dependencies = [ | |
11 | + ('core', '0008_resource_link'), | |
12 | + ] | |
13 | + | |
14 | + operations = [ | |
15 | + migrations.RenameField( | |
16 | + model_name='resource', | |
17 | + old_name='link', | |
18 | + new_name='url', | |
19 | + ), | |
20 | + ] | ... | ... |
core/models.py
... | ... | @@ -34,7 +34,7 @@ class Resource(models.Model): |
34 | 34 | |
35 | 35 | name = models.CharField(_('Name'), max_length =100, unique=True) |
36 | 36 | created_date = models.DateField(_('Created Date'), auto_now_add=True) |
37 | - link = models.CharField(_('URL'), max_length =100, default="") | |
37 | + url = models.CharField(_('URL'), max_length =100, default="") | |
38 | 38 | |
39 | 39 | |
40 | 40 | class Meta: | ... | ... |
core/static/css/base/amadeus.css
... | ... | @@ -250,3 +250,15 @@ li.alert_li:hover{background-color:#eee} |
250 | 250 | .turn_off_alert{float:right;margin-bottom :1px} |
251 | 251 | a.alert_message{color : grey} |
252 | 252 | a.alert_message:hover{color : grey} |
253 | + | |
254 | +/*=================== Ailson - Please Don't touch*/ | |
255 | +.breadcrumb .divider{ | |
256 | + display: none; | |
257 | +} | |
258 | + | |
259 | +.accordion { | |
260 | + background: #c0c0c0; | |
261 | +} | |
262 | +.accordion_list { | |
263 | + background: #e0e0e0; | |
264 | +} | ... | ... |
2.99 KB
core/templates/base.html
... | ... | @@ -48,7 +48,7 @@ |
48 | 48 | <span class="icon-bar"></span> |
49 | 49 | <span class="icon-bar"></span> |
50 | 50 | </button> |
51 | - <a class="navbar-brand" href="javascript:void(0)"><img class="logo" src="{% static 'img/topo-amadeus.png' %}" alt="Logo"/></a> | |
51 | + <a class="navbar-brand" href="{% url 'app:index' %}"><img class="logo" src="{% static 'img/topo-amadeus.png' %}" alt="Logo"/></a> | |
52 | 52 | </div> |
53 | 53 | <div class="navbar-collapse collapse navbar-responsive-collapse"> |
54 | 54 | <ul class="nav navbar-nav navbar-right notifications"> | ... | ... |
... | ... | @@ -0,0 +1,14 @@ |
1 | +from .models import Course | |
2 | + | |
3 | +def courses(request): | |
4 | + if request.user.is_authenticated: | |
5 | + context = {} | |
6 | + | |
7 | + if request.user.is_staff: | |
8 | + context['courses_list'] = Course.objects.all() | |
9 | + else: | |
10 | + context['courses_list'] = Course.objects.filter(professors__in = [request.user]) | |
11 | + | |
12 | + return context | |
13 | + else: | |
14 | + return request | |
0 | 15 | \ No newline at end of file | ... | ... |
courses/forms.py
1 | + | |
1 | 2 | from django import forms |
2 | 3 | from django.utils.translation import ugettext_lazy as _ |
3 | 4 | from .models import Category, Course, Subject, Topic |
... | ... | @@ -17,6 +18,29 @@ class CategoryForm(forms.ModelForm): |
17 | 18 | |
18 | 19 | |
19 | 20 | class CourseForm(forms.ModelForm): |
21 | + def clean_end_register_date(self): | |
22 | + init_register_date = self.data['init_register_date'] | |
23 | + end_register_date = self.data['end_register_date'] | |
24 | + | |
25 | + if init_register_date and end_register_date and end_register_date < init_register_date: | |
26 | + raise forms.ValidationError(_('The end date may not be before the start date.')) | |
27 | + return end_register_date | |
28 | + | |
29 | + def clean_init_date(self): | |
30 | + end_register_date = self.data['end_register_date'] | |
31 | + init_date = self.data['init_date'] | |
32 | + | |
33 | + if end_register_date and init_date and init_date <= end_register_date: | |
34 | + raise forms.ValidationError(_('The course start date must be after the end of registration.')) | |
35 | + return init_date | |
36 | + | |
37 | + def clean_end_date(self): | |
38 | + init_date = self.data['init_date'] | |
39 | + end_date = self.data['end_date'] | |
40 | + | |
41 | + if init_date and end_date and end_date < init_date: | |
42 | + raise forms.ValidationError(_('The end date may not be before the start date.')) | |
43 | + return end_date | |
20 | 44 | |
21 | 45 | # init_register_date = forms.DateField(widget=forms.DateField) |
22 | 46 | # end_register_date = forms.DateField(widget=forms.DateField) |
... | ... | @@ -53,6 +77,53 @@ class CourseForm(forms.ModelForm): |
53 | 77 | 'category': _('Category which the course belongs'), |
54 | 78 | } |
55 | 79 | |
80 | + widgets = { | |
81 | + 'categoy': forms.Select(), | |
82 | + 'objectivies': forms.Textarea(attrs={'cols': 80, 'rows': 5}), | |
83 | + 'content': forms.Textarea(attrs={'cols': 80, 'rows': 5}), | |
84 | + } | |
85 | + | |
86 | +class UpdateCourseForm(CourseForm): | |
87 | + def __init__(self, *args, **kwargs): | |
88 | + super(UpdateCourseForm, self).__init__(*args, **kwargs) | |
89 | + self.fields["students"].required = False | |
90 | + | |
91 | + class Meta: | |
92 | + model = Course | |
93 | + fields = ('name', 'objectivies', 'content', 'max_students', 'init_register_date', 'end_register_date', | |
94 | + 'init_date', 'end_date', 'image', 'category','students',) | |
95 | + labels = { | |
96 | + 'name': _('Name'), | |
97 | + 'objectivies': _('Objectives'), | |
98 | + 'content': _('Content'), | |
99 | + 'max_students': _('Number of studets maximum'), | |
100 | + 'init_register_date': _('Course registration start date'), | |
101 | + 'end_register_date': _('Course registration end date'), | |
102 | + 'init_date': _('Course start date'), | |
103 | + 'end_date': _('Course end date'), | |
104 | + 'image': _('Image'), | |
105 | + 'category': _('Category'), | |
106 | + 'students': _('Student'), | |
107 | + } | |
108 | + help_texts = { | |
109 | + 'name': _('Course name'), | |
110 | + 'objectivies': _('Course objective'), | |
111 | + 'content': _('Course modules'), | |
112 | + 'max_students': _('Max number of students that a class can have'), | |
113 | + 'init_register_date': _('Date that starts the registration period of the course (dd/mm/yyyy)'), | |
114 | + 'end_register_date': _('Date that ends the registration period of the course (dd/mm/yyyy)'), | |
115 | + 'init_date': _('Date that the course starts (dd/mm/yyyy)'), | |
116 | + 'end_date': _('Date that the course ends (dd/mm/yyyy)'), | |
117 | + 'image': _('Representative image of the course'), | |
118 | + 'category': _('Category which the course belongs'), | |
119 | + 'students': _("Course's Students"), | |
120 | + } | |
121 | + widgets = { | |
122 | + 'categoy': forms.Select(), | |
123 | + 'objectivies': forms.Textarea(attrs={'cols': 80, 'rows': 5}), | |
124 | + 'content': forms.Textarea(attrs={'cols': 80, 'rows': 5}), | |
125 | + } | |
126 | + | |
56 | 127 | class SubjectForm(forms.ModelForm): |
57 | 128 | |
58 | 129 | class Meta: | ... | ... |
... | ... | @@ -0,0 +1,28 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Generated by Django 1.10 on 2016-09-16 03:01 | |
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 | + ('courses', '0012_course_students'), | |
13 | + ] | |
14 | + | |
15 | + operations = [ | |
16 | + migrations.AddField( | |
17 | + model_name='subject', | |
18 | + name='end_date', | |
19 | + field=models.DateField(default=django.utils.timezone.now, verbose_name='End of Subject Date'), | |
20 | + preserve_default=False, | |
21 | + ), | |
22 | + migrations.AddField( | |
23 | + model_name='subject', | |
24 | + name='init_date', | |
25 | + field=models.DateField(default=django.utils.timezone.now, verbose_name='Begin of Subject Date'), | |
26 | + preserve_default=False, | |
27 | + ), | |
28 | + ] | ... | ... |
... | ... | @@ -0,0 +1,48 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Generated by Django 1.10 on 2016-09-16 04:26 | |
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 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | |
14 | + ('core', '0009_auto_20160916_0126'), | |
15 | + ('courses', '0012_course_students'), | |
16 | + ] | |
17 | + | |
18 | + operations = [ | |
19 | + migrations.CreateModel( | |
20 | + name='Activity', | |
21 | + fields=[ | |
22 | + ('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')), | |
23 | + ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), | |
24 | + ('limit_date', models.DateTimeField(verbose_name='Deliver Date')), | |
25 | + ('grade', models.IntegerField(verbose_name='grade')), | |
26 | + ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student', to=settings.AUTH_USER_MODEL, verbose_name='student')), | |
27 | + ], | |
28 | + bases=('core.resource',), | |
29 | + ), | |
30 | + migrations.CreateModel( | |
31 | + name='Link', | |
32 | + fields=[ | |
33 | + ('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')), | |
34 | + ('url_field', models.CharField(max_length=300, verbose_name='url')), | |
35 | + ], | |
36 | + bases=('core.resource',), | |
37 | + ), | |
38 | + migrations.AddField( | |
39 | + model_name='topic', | |
40 | + name='visible', | |
41 | + field=models.BooleanField(default=False, verbose_name='Visible'), | |
42 | + ), | |
43 | + migrations.AddField( | |
44 | + model_name='activity', | |
45 | + name='topic', | |
46 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='topic', to='courses.Topic', verbose_name='Topic'), | |
47 | + ), | |
48 | + ] | ... | ... |
... | ... | @@ -0,0 +1,16 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Generated by Django 1.10 on 2016-09-16 05:55 | |
3 | +from __future__ import unicode_literals | |
4 | + | |
5 | +from django.db import migrations | |
6 | + | |
7 | + | |
8 | +class Migration(migrations.Migration): | |
9 | + | |
10 | + dependencies = [ | |
11 | + ('courses', '0013_auto_20160916_0001'), | |
12 | + ('courses', '0013_auto_20160916_0126'), | |
13 | + ] | |
14 | + | |
15 | + operations = [ | |
16 | + ] | ... | ... |
courses/models.py
... | ... | @@ -2,6 +2,7 @@ from django.utils.translation import ugettext_lazy as _ |
2 | 2 | from django.db import models |
3 | 3 | from autoslug.fields import AutoSlugField |
4 | 4 | from users.models import User |
5 | +from core.models import Resource | |
5 | 6 | |
6 | 7 | class Category(models.Model): |
7 | 8 | |
... | ... | @@ -47,6 +48,8 @@ class Subject(models.Model): |
47 | 48 | slug = AutoSlugField(_("Slug"),populate_from='name',unique=True) |
48 | 49 | description = models.TextField(_('Description'), blank = True) |
49 | 50 | visible = models.BooleanField(_('Visible'), default = False) |
51 | + init_date = models.DateField(_('Begin of Subject Date')) | |
52 | + end_date = models.DateField(_('End of Subject Date')) | |
50 | 53 | create_date = models.DateTimeField(_('Creation Date'), auto_now_add = True) |
51 | 54 | update_date = models.DateTimeField(_('Date of last update'), auto_now=True) |
52 | 55 | course = models.ForeignKey(Course, verbose_name = _('Course'), related_name="subjects") |
... | ... | @@ -70,6 +73,7 @@ class Topic(models.Model): |
70 | 73 | update_date = models.DateTimeField(_('Date of last update'), auto_now=True) |
71 | 74 | subject = models.ForeignKey(Subject, verbose_name = _('Subject'), related_name="topics") |
72 | 75 | owner = models.ForeignKey(User, verbose_name = _('Owner'), related_name="topics") |
76 | + visible = models.BooleanField(_('Visible'), default=False) | |
73 | 77 | |
74 | 78 | class Meta: |
75 | 79 | ordering = ('create_date','name') |
... | ... | @@ -78,3 +82,21 @@ class Topic(models.Model): |
78 | 82 | |
79 | 83 | def __str__(self): |
80 | 84 | return self.name |
85 | + | |
86 | +""" | |
87 | +It is one kind of possible resources available inside a Topic. | |
88 | +Activity is something that has a deadline and has to be delivered by the student | |
89 | +""" | |
90 | +class Activity(Resource): | |
91 | + create_date = models.DateTimeField(_('Creation Date'), auto_now_add = True) | |
92 | + topic = models.ForeignKey(Topic, verbose_name = _('Topic'), related_name="topic") | |
93 | + create_date = models.DateTimeField(_('Creation Date'), auto_now_add = True) | |
94 | + limit_date = models.DateTimeField(_('Deliver Date')) | |
95 | + student = models.ForeignKey(User, verbose_name = _('student'), related_name="student") | |
96 | + grade = models.IntegerField(_('grade')) | |
97 | + | |
98 | +""" | |
99 | +It is one kind of possible resources available inside a Topic. | |
100 | +""" | |
101 | +class Link(Resource): | |
102 | + url_field = models.CharField(_('url'), max_length= 300) | |
81 | 103 | \ No newline at end of file | ... | ... |
courses/permissions.py
... | ... | @@ -30,3 +30,23 @@ def delete_subject(role, user, subject): |
30 | 30 | return True |
31 | 31 | |
32 | 32 | return False |
33 | + | |
34 | +@register_object_checker() | |
35 | +def update_course(role, user, course): | |
36 | + if (role == SystemAdmin): | |
37 | + return True | |
38 | + | |
39 | + if (user in course.professors.all()): | |
40 | + return True | |
41 | + | |
42 | + return False | |
43 | + | |
44 | +@register_object_checker() | |
45 | +def delete_course(role, user, course): | |
46 | + if (role == SystemAdmin): | |
47 | + return True | |
48 | + | |
49 | + if (user in course.professors.all()): | |
50 | + return True | |
51 | + | |
52 | + return False | ... | ... |
courses/templates/course/create.html
1 | -{% extends 'app/base.html' %} | |
1 | +{% extends 'course/view.html' %} | |
2 | 2 | |
3 | 3 | {% load static i18n %} |
4 | 4 | {% load widget_tweaks %} |
... | ... | @@ -10,16 +10,9 @@ |
10 | 10 | </ol> |
11 | 11 | {% endblock %} |
12 | 12 | |
13 | -{% block sidebar %} | |
14 | - <div class="list-group"> | |
15 | - <a href="{% url 'course:manage' %}" class="list-group-item"> | |
16 | - {% trans 'Courses' %} | |
17 | - </a> | |
18 | - </div> | |
19 | -{% endblock %} | |
20 | - | |
21 | 13 | {% block content %} |
22 | 14 | |
15 | +<<<<<<< HEAD | |
23 | 16 | <form method="post" action="" enctype="multipart/form-data"> |
24 | 17 | {% csrf_token %} |
25 | 18 | {% for field in form %} |
... | ... | @@ -46,4 +39,56 @@ |
46 | 39 | <input type="submit" value="{% trans 'Save' %}" class="btn btn-sm btn-success" /> |
47 | 40 | </form> |
48 | 41 | <br clear="all" /> |
42 | +======= | |
43 | +</br> | |
44 | +<div class="card card-content"> | |
45 | + <div class="card-body"> | |
46 | + <form method="post" action="" enctype="multipart/form-data"> | |
47 | + {% csrf_token %} | |
48 | + {% for field in form %} | |
49 | + <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput"> | |
50 | + <label for="{{ field.auto_id }}">{{ field.label }}</label> | |
51 | + {% if field.auto_id == 'id_init_register_date' or field.auto_id == 'id_end_register_date' or field.auto_id == 'id_init_date' or field.auto_id == 'id_end_date'%} | |
52 | + <input type="date" class="form-control"name="{{field.name}}" value="{% if field.value.year %}{{field.value|date:'Y-m-d'}}{% else %}{{field.value}}{% endif %}" min="{{now|date:'Y-m-d'}}"> | |
53 | + {% elif field.auto_id == 'id_image' %} | |
54 | + {% render_field field class='form-control' %} | |
55 | + <div class="input-group"> | |
56 | + <input type="text" readonly="" class="form-control" placeholder="Choose your photo..."/> | |
57 | + <span class="input-group-btn input-group-sm"> | |
58 | + <button type="button" class="btn btn-fab btn-fab-mini"> | |
59 | + <i class="material-icons">attach_file</i> | |
60 | + </button> | |
61 | + </span> | |
62 | + </div> | |
63 | + {% else %} | |
64 | + {% render_field field class='form-control' %} | |
65 | + {% endif %} | |
66 | + <span class="help-block">{{ field.help_text }}</span> | |
67 | + {% if field.errors %} | |
68 | + <div class="row"> | |
69 | + </br> | |
70 | + <div class="alert alert-danger alert-dismissible" role="alert"> | |
71 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
72 | + <span aria-hidden="true">×</span> | |
73 | + </button> | |
74 | + <ul> | |
75 | + {% for error in field.errors %} | |
76 | + <li>{{ error }}</li> | |
77 | + {% endfor %} | |
78 | + </ul> | |
79 | + </div> | |
80 | + </div> | |
81 | + {% endif %} | |
82 | + </div> | |
83 | + {% endfor %} | |
84 | + <div class="row text-center"> | |
85 | + <input type="submit" value="{% trans 'Create' %}" class="btn btn-primary" /> | |
86 | + </div> | |
87 | + </form> | |
88 | + </div> | |
89 | +</div> | |
90 | +</br> | |
91 | +</br> | |
92 | +</br> | |
93 | +>>>>>>> 841817e1db11c57551cb8e21bf361e5bf6c9d982 | |
49 | 94 | {% endblock %} | ... | ... |
courses/templates/course/delete.html
1 | -{% extends 'app/base.html' %} | |
1 | +{% extends 'course/view.html' %} | |
2 | 2 | |
3 | 3 | {% load static i18n %} |
4 | 4 | |
... | ... | @@ -9,23 +9,15 @@ |
9 | 9 | </ol> |
10 | 10 | {% endblock %} |
11 | 11 | |
12 | -{% block sidebar %} | |
13 | - <div class="list-group"> | |
14 | - <a href="{% url 'course:manage' %}" class="list-group-item"> | |
15 | - {% trans 'Courses' %} | |
16 | - </a> | |
17 | - <a href="{% url 'course:create' %}" class="list-group-item"> | |
18 | - {% trans 'Create Course' %} | |
19 | - </a> | |
20 | - </div> | |
21 | - | |
22 | -{% endblock %} | |
23 | - | |
24 | 12 | {% block content %} |
25 | - <form action="" method="post"> | |
26 | - {% csrf_token %} | |
27 | - <p>{% trans 'Are you sure you want to delete the couse' %} "{{ object }}"?</p> | |
28 | - <input type="submit" class="btn btn-success btn-sm" value="{% trans 'Yes' %}" /> | |
29 | - <a href="{% url 'course:manage' %}" class="btn btn-danger btn-sm">{% trans 'No' %}</a> | |
30 | - </form> | |
13 | +<div class="panel panel-default"> | |
14 | + <div class="panel-body"> | |
15 | + <form action="" method="post"> | |
16 | + {% csrf_token %} | |
17 | + <h2>{% trans 'Are you sure you want to delete the course' %} "{{course}}"?</h2> | |
18 | + <input type="submit" class="btn btn-raised btn-success btn-lg" value="{% trans 'Yes' %}" /> | |
19 | + <a href="{% url 'course:view' course.slug%}" class="btn btn-raised btn-danger btn-lg">{% trans 'No' %}</a> | |
20 | + </form> | |
21 | + </div> | |
22 | +</div> | |
31 | 23 | {% endblock %} | ... | ... |
courses/templates/course/index.html
... | ... | @@ -54,7 +54,11 @@ |
54 | 54 | {% for course in courses %} |
55 | 55 | <div class="row well well-inverse"> |
56 | 56 | <div class="col-md-2"> |
57 | + {% if course.image %} | |
57 | 58 | <img src="{{ course.image.url }}" class="img-responsive" /> |
59 | + {% else %} | |
60 | + <img src="" class="img-responsive" /> | |
61 | + {% endif %} | |
58 | 62 | </div> |
59 | 63 | <div class="col-md-10"> |
60 | 64 | <div class="row"> | ... | ... |
courses/templates/course/update.html
1 | -{% extends 'app/base.html' %} | |
1 | +{% extends 'course/view.html' %} | |
2 | 2 | |
3 | 3 | {% load static i18n %} |
4 | 4 | {% load widget_tweaks %} |
5 | 5 | |
6 | 6 | {% block breadcrumbs %} |
7 | 7 | <ol class="breadcrumb"> |
8 | - <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> | |
9 | - <li class="active">{% trans 'Edit Course' %}</li> | |
8 | + <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> | |
9 | + <li class="active">{% trans 'Edit Course' %}</li> | |
10 | 10 | </ol> |
11 | 11 | {% endblock %} |
12 | - | |
13 | -{% block sidebar %} | |
14 | - <div class="list-group"> | |
15 | - <a href="{% url 'course:manage' %}" class="list-group-item"> | |
16 | - {% trans 'Courses' %} | |
17 | - </a> | |
18 | - <a href="{% url 'course:manage_mods' course.slug %}" class="list-group-item"> | |
19 | - {% trans 'Manage Modules' %} | |
20 | - </a> | |
21 | - <a href="#" class="list-group-item"> | |
22 | - {% trans 'Participants' %} | |
23 | - </a> | |
24 | - </div> | |
25 | -{% endblock %} | |
26 | - | |
27 | 12 | {% block content %} |
28 | - <div class="alert alert-info alert-dismissible" role="alert"> | |
29 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
30 | - <span aria-hidden="true">×</span> | |
31 | - </button> | |
32 | - <p>{% trans 'All fields are required' %}</p> | |
33 | - </div> | |
34 | 13 | |
35 | - <form method="post" action="" enctype="multipart/form-data"> | |
36 | - {% csrf_token %} | |
37 | - {% for field in form %} | |
38 | - <div class="form-group{% if form.has_error %} has-error {% endif %}"> | |
39 | - <label for="{{ field.auto_id }}">{{ field.label }}</label> | |
40 | - {% render_field field class='form-control input-sm' %} | |
41 | - <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
42 | - {% if field.errors.length > 0 %} | |
43 | - <div class="alert alert-danger alert-dismissible" role="alert"> | |
44 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
45 | - <span aria-hidden="true">×</span> | |
46 | - </button> | |
47 | - <ul> | |
48 | - {% for error in field.errors %} | |
49 | - <li>{{ error }}</li> | |
50 | - {% endfor %} | |
51 | - </ul> | |
14 | +</br> | |
15 | +<div class="card card-content"> | |
16 | + <div class="card-body"> | |
17 | + <form method="post" action="" enctype="multipart/form-data"> | |
18 | + {% csrf_token %} | |
19 | + {% for field in form %} | |
20 | + <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput"> | |
21 | + <label for="{{ field.auto_id }}">{{ field.label }}</label> | |
22 | + {% if field.auto_id == 'id_init_register_date' or field.auto_id == 'id_end_register_date' or field.auto_id == 'id_init_date' or field.auto_id == 'id_end_date'%} | |
23 | + <input type="date" class="form-control"name="{{field.name}}" value="{% if field.value.year %}{{field.value|date:'Y-m-d'}}{% else %}{{field.value}}{% endif %}" min="{{now|date:'Y-m-d'}}"> | |
24 | + {% elif field.auto_id == 'id_image' %} | |
25 | + {% render_field field class='form-control' %} | |
26 | + <div class="input-group"> | |
27 | + <input type="text" readonly="" class="form-control" placeholder="Choose your photo..."/> | |
28 | + <span class="input-group-btn input-group-sm"> | |
29 | + <button type="button" class="btn btn-fab btn-fab-mini"> | |
30 | + <i class="material-icons">attach_file</i> | |
31 | + </button> | |
32 | + </span> | |
33 | + </div> | |
34 | + {% else %} | |
35 | + {% render_field field class='form-control' %} | |
36 | + {% endif %} | |
37 | + <span class="help-block">{{ field.help_text }}</span> | |
38 | + {% if field.errors %} | |
39 | + <div class="row"> | |
40 | + </br> | |
41 | + <div class="alert alert-danger alert-dismissible" role="alert"> | |
42 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
43 | + <span aria-hidden="true">×</span> | |
44 | + </button> | |
45 | + <ul> | |
46 | + {% for error in field.errors %} | |
47 | + <li>{{ error }}</li> | |
48 | + {% endfor %} | |
49 | + </ul> | |
50 | + </div> | |
52 | 51 | </div> |
52 | + {% endif %} | |
53 | 53 | </div> |
54 | - {% endif %} | |
54 | + {% endfor %} | |
55 | + <div class="row text-center"> | |
56 | + <input type="submit" value="{% trans 'Update' %}" class="btn btn-primary" /> | |
55 | 57 | </div> |
56 | - {% endfor %} | |
57 | - <input type="submit" value="{% trans 'Save' %}" class="btn btn-sm btn-success" /> | |
58 | - </form> | |
59 | - <br clear="all" /> | |
58 | + </form> | |
59 | + </div> | |
60 | +</div> | |
61 | +</br> | |
62 | +</br> | |
63 | +</br> | |
60 | 64 | {% endblock %} | ... | ... |
courses/templates/course/view.html
... | ... | @@ -15,9 +15,24 @@ |
15 | 15 | {% endblock %} |
16 | 16 | |
17 | 17 | {% block sidebar %} |
18 | -<div class="panel panel-primary navigation"> | |
18 | +<div class="panel panel-primary"> | |
19 | 19 | <div class="panel-heading"> |
20 | - <h5>{% trans "Menu" %}</h5> | |
20 | + <img src="{{ user.image.url }}" id="img" class="img-circle img-responsive"> | |
21 | + </br> | |
22 | + <div class="row"> | |
23 | + <div class="col-xs-3 col-md-3"> | |
24 | + <i class="fa fa-facebook-official fa-2x" aria-hidden="true"></i> | |
25 | + </div> | |
26 | + <div class="col-xs-3 col-md-3"> | |
27 | + <i class="fa fa-twitter fa-2x" aria-hidden="true"></i> | |
28 | + </div> | |
29 | + <div class="col-xs-3 col-md-3"> | |
30 | + <i class="fa fa-linkedin-square fa-2x" aria-hidden="true"></i> | |
31 | + </div> | |
32 | + <div class="col-xs-3 col-md-3"> | |
33 | + <i class="fa fa-google-plus-official fa-2x" aria-hidden="true"></i> | |
34 | + </div> | |
35 | + </div> | |
21 | 36 | </div> |
22 | 37 | <div class="panel-body"> |
23 | 38 | <ul class="nav nav-pills nav-stacked"> |
... | ... | @@ -28,7 +43,7 @@ |
28 | 43 | </div> |
29 | 44 | </div> |
30 | 45 | {% if courses.count > 0 %} |
31 | -<div class="panel panel-primary navigation"> | |
46 | +<div class="panel panel-primary"> | |
32 | 47 | <div class="panel-heading"> |
33 | 48 | <h5>{% trans "Courses" %}</h5> |
34 | 49 | </div> |
... | ... | @@ -49,22 +64,24 @@ |
49 | 64 | <div class="panel panel-info"> |
50 | 65 | <div class="panel-heading"> |
51 | 66 | <div class="row"> |
52 | -<div class="col-md-10"> | |
67 | + <a href="{% url 'course:view_subject' subject.slug %}"> | |
68 | + <div class="col-md-10"> | |
53 | 69 | |
54 | - <h3 class="panel-title"><a href="{% url 'course:view_subject' subject.slug %}"></a>{{subject}}</h3> | |
70 | + <h3 class="panel-title">{{subject}}</h3> | |
55 | 71 | |
56 | - </div> | |
57 | - <div class="col-md-2 text-right"> | |
58 | - {% if user|has_role:'professor, system_admin' %} | |
59 | - <a href="{% url 'course:update_subject' subject.slug %}" style="padding: 3px; margin: 3px;" class="btn btn-sm btn-default"> | |
60 | - <span class="glyphicon glyphicon-edit"></span> | |
61 | - </a> | |
62 | - <a href="{% url 'course:delete_subject' subject.slug %}" style="padding: 3px; margin: 3px;" class="btn btn-sm btn-danger"> | |
63 | - <span class="glyphicon glyphicon-trash"></span> | |
64 | - </a> | |
65 | - {% endif %} | |
66 | - </div> | |
67 | -</div> | |
72 | + </div> | |
73 | + </a> | |
74 | + <div class="col-md-2 text-right"> | |
75 | + {% if user|has_role:'professor, system_admin' %} | |
76 | + <a href="{% url 'course:update_subject' subject.slug %}" style="padding: 3px; margin: 3px;" class="btn btn-sm btn-default"> | |
77 | + <span class="glyphicon glyphicon-edit"></span> | |
78 | + </a> | |
79 | + <a href="{% url 'course:delete_subject' subject.slug %}" style="padding: 3px; margin: 3px;" class="btn btn-sm btn-danger"> | |
80 | + <span class="glyphicon glyphicon-trash"></span> | |
81 | + </a> | |
82 | + {% endif %} | |
83 | + </div> | |
84 | + </div> | |
68 | 85 | </div> |
69 | 86 | <div class="panel-body"> |
70 | 87 | <p><b>{% trans "Professor" %}: </b>{% for professor in subject.professors.all %}{% if not forloop.first %},{% endif %} |
... | ... | @@ -77,10 +94,10 @@ |
77 | 94 | </p> |
78 | 95 | <div class="row"> |
79 | 96 | <div class="col-xs-6 col-md-6"> |
80 | - {# <p><b>{% trans "Begining" %}: </b>{{subject.init_date}}</p>#} | |
97 | + <p><b>{% trans "Begining" %}: </b>{{subject.init_date}}</p> | |
81 | 98 | </div> |
82 | 99 | <div class="col-xs-6 col-md-6"> |
83 | - {# <p><b>End: </b>23/08/2019</p>#} | |
100 | + <p><b>{% trans "End" %}: </b>{{subject.end_date}}</p> | |
84 | 101 | </div> |
85 | 102 | </div> |
86 | 103 | </div> |
... | ... | @@ -90,5 +107,12 @@ |
90 | 107 | |
91 | 108 | |
92 | 109 | {% block rightbar %} |
93 | - | |
110 | +<div class="panel panel-warning"> | |
111 | + <div class="panel-heading"> | |
112 | + <h3 class="panel-title">{% trans "Pending Stuffs" %}</h3> | |
113 | + </div> | |
114 | + <div class="panel-body"> | |
115 | + <p>{% trans 'No pending tasks at the moment.' %}</p> | |
116 | + </div> | |
117 | + </div> | |
94 | 118 | {% endblock rightbar %} | ... | ... |
courses/templates/subject/delete.html
... | ... | @@ -8,7 +8,7 @@ |
8 | 8 | <div class="panel-body"> |
9 | 9 | <form action="" method="post"> |
10 | 10 | {% csrf_token %} |
11 | - <h2>{% trans 'Are you sure you want to delete the category' %} "{{subject}}"?</h2> | |
11 | + <h2>{% trans 'Are you sure you want to delete the subject' %} "{{subject}}"?</h2> | |
12 | 12 | <input type="submit" class="btn btn-raised btn-success btn-lg" value="{% trans 'Yes' %}" /> |
13 | 13 | <a href="{% url 'course:view_subject' subject.slug%}" class="btn btn-raised btn-danger btn-lg">{% trans 'No' %}</a> |
14 | 14 | </form> | ... | ... |
courses/templates/subject/form_view_student.html
1 | 1 | {% load i18n %} |
2 | 2 | |
3 | 3 | <div class="panel panel-default"> |
4 | + <a href="{% url 'course:view_topic' topic.slug %}"> | |
4 | 5 | <div class="panel-heading"> |
5 | 6 | <div class="row"> |
6 | 7 | <div class="col-md-9 col-sm-9"> |
7 | 8 | <h3>{{topic}}</h3> |
8 | 9 | </div> |
9 | 10 | </div> |
11 | + </div> | |
12 | + </a> | |
10 | 13 | </div> |
14 | + | |
11 | 15 | <div class="panel-body"> |
12 | 16 | <p>{{topic.description|linebreaks}}</p> |
13 | 17 | </div> | ... | ... |
courses/templates/subject/form_view_teacher.html
1 | 1 | {% load i18n %} |
2 | 2 | |
3 | 3 | <div class="panel panel-default"> |
4 | + <a href="{% url 'course:view_topic' topic.slug %}"> | |
4 | 5 | <div class="panel-heading"> |
5 | 6 | <div class="row"> |
6 | 7 | <div class="col-md-9 col-sm-9"> |
... | ... | @@ -11,6 +12,7 @@ |
11 | 12 | </div> |
12 | 13 | </div> |
13 | 14 | </div> |
15 | + </a> | |
14 | 16 | <div class="panel-body"> |
15 | 17 | <p>{{topic.description|linebreaks}}</p> |
16 | 18 | </div> | ... | ... |
courses/templates/subject/index.html
... | ... | @@ -7,7 +7,12 @@ |
7 | 7 | <ol class="breadcrumb"> |
8 | 8 | <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> |
9 | 9 | <li><a href="{% url 'course:view' course.slug %}">{{ course }}</a></li> |
10 | - <li class="active">{% trans 'Manage Subjects' %}</li> | |
10 | + {% if user|has_role:'professor' or user|has_role:'system_admin' %} | |
11 | + <li class="active">{% trans 'Manage Subjects' %}</li> | |
12 | + {% else %} | |
13 | + <li class="active">{{ subject.name }}</li> | |
14 | + {% endif %} | |
15 | + | |
11 | 16 | </ol> |
12 | 17 | {% endblock %} |
13 | 18 | |
... | ... | @@ -67,8 +72,10 @@ |
67 | 72 | {% include "subject/form_view_student.html" %} |
68 | 73 | {% endif %} |
69 | 74 | {% endfor %} |
75 | + {% if user|has_role:'system_admin' or topic.owner == user%} | |
76 | + <a name="create_topic" class="btn btn-primary btn-md btn-block" href="{% url 'course:create_topic' subject.slug %}">{% trans "Create Topic" %}</a> | |
77 | + {% endif %} | |
70 | 78 | |
71 | - <a name="create_topic" class="btn btn-primary btn-md btn-block" href="{% url 'course:create_topic' subject.slug %}">{% trans "Create Topic" %}</a> | |
72 | 79 | {% endblock %} |
73 | 80 | |
74 | 81 | {% block rightbar %} | ... | ... |
... | ... | @@ -0,0 +1,89 @@ |
1 | +{% extends 'base.html' %} | |
2 | + | |
3 | +{% load static i18n permission_tags %} | |
4 | + | |
5 | +{% block breadcrumbs %} | |
6 | + | |
7 | + <ol class="breadcrumb"> | |
8 | + <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> | |
9 | + <li><a href="{% url 'course:view_subject' subject.slug %}">{{ subject }}</a></li> | |
10 | + {% if user|has_role:'professor' or user|has_role:'system_admin' %} | |
11 | + <li class="active">{% trans 'Manage Topic' %}</li> | |
12 | + {% else %} | |
13 | + <li class="active">{{ topic.name }}</li> | |
14 | + {% endif %} | |
15 | + | |
16 | + </ol> | |
17 | +{% endblock %} | |
18 | + | |
19 | +{% block sidebar %} | |
20 | + | |
21 | + <div class="panel panel-primary"> | |
22 | + | |
23 | + <div class="panel-heading"> | |
24 | + <h3 class="panel-title">{{course}}</h3> | |
25 | + </div> | |
26 | + | |
27 | + <div class="panel-body"> | |
28 | + <!--{% for subject in subjects %} | |
29 | + <div class="row"> | |
30 | + <div class="col-md-12 col-sm-12"> | |
31 | + {{subject}} | |
32 | + </div> | |
33 | + </div> | |
34 | + {% endfor %}--> | |
35 | + </div> | |
36 | + </div> | |
37 | + | |
38 | + | |
39 | +{% endblock %} | |
40 | + | |
41 | +{% block content %} | |
42 | + <div class="panel panel-info"> | |
43 | + <div class="panel-heading"> | |
44 | + <div class="row"> | |
45 | + <div class="col-md-7 col-sm-7"> | |
46 | + <h3>{{subject}}</h3> | |
47 | + </div> | |
48 | + <div class="col-md-2 col-sm-2"> | |
49 | + {% if user|has_role:'system_admin' or user in subject.professors %} | |
50 | + <a href="{% url 'course:update_subject' subject.slug%}" class="btn">{% trans "edit" %}</a> | |
51 | + {% endif %} | |
52 | + </div> | |
53 | + <div class="col-md-3 col-sm-3"> | |
54 | + {% if user|has_role:'system_admin' or user in subject.professors %} | |
55 | + <a href="{% url 'course:delete_subject' subject.slug%}" class="btn">{% trans "delete" %}</a> | |
56 | + {% endif %} | |
57 | + </div> | |
58 | + </div> | |
59 | + </div> | |
60 | + <div class="panel-body"> | |
61 | + <p> | |
62 | + {{subject.description|linebreaks}} | |
63 | + </p> | |
64 | + </div> | |
65 | + </div> | |
66 | +<!--{% for topic in topics %} | |
67 | + {% if user|has_role:'system_admin' or topic.owner == user%} | |
68 | + {% include "subject/form_view_teacher.html" %} | |
69 | + {% else %} | |
70 | + {% include "subject/form_view_student.html" %} | |
71 | + {% endif %} | |
72 | +{% endfor %} | |
73 | + {% if user|has_role:'system_admin' or topic.owner == user%} | |
74 | + <a name="create_topic" class="btn btn-primary btn-md btn-block" href="{% url 'course:create_topic' subject.slug %}">{% trans "Create Topic" %}</a> | |
75 | + {% endif %} | |
76 | + | |
77 | +{% endblock %}--> | |
78 | + | |
79 | +{% block rightbar %} | |
80 | + | |
81 | + <div class="panel panel-warning"> | |
82 | + <div class="panel-heading"> | |
83 | + <h3 class="panel-title">{% trans "Pending Stuffs" %}</h3> | |
84 | + </div> | |
85 | + <div class="panel-body"> | |
86 | + | |
87 | + </div> | |
88 | + </div> | |
89 | +{% endblock rightbar %} | ... | ... |
courses/urls.py
... | ... | @@ -4,10 +4,10 @@ from . import views |
4 | 4 | |
5 | 5 | urlpatterns = [ |
6 | 6 | url(r'^$', views.IndexView.as_view(), name='manage'), |
7 | - url(r'^create/$', views.CreateView.as_view(), name='create'), | |
8 | - url(r'^edit/(?P<slug>[\w_-]+)/$', views.UpdateView.as_view(), name='update'), | |
7 | + url(r'^create/$', views.CreateCourseView.as_view(), name='create'), | |
8 | + url(r'^edit/(?P<slug>[\w_-]+)/$', views.UpdateCourseView.as_view(), name='update'), | |
9 | 9 | url(r'^(?P<slug>[\w_-]+)/$', views.CourseView.as_view(), name='view'), |
10 | - url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteView.as_view(), name='delete'), | |
10 | + url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteCourseView.as_view(), name='delete'), | |
11 | 11 | url(r'^category/(?P<slug>[\w_-]+)/$', views.FilteredView.as_view(), name='filter'), |
12 | 12 | url(r'^categories/$', views.IndexCatView.as_view(), name='manage_cat'), |
13 | 13 | url(r'^categories/create/$', views.CreateCatView.as_view(), name="create_cat"), |
... | ... | @@ -15,9 +15,10 @@ urlpatterns = [ |
15 | 15 | url(r'^categories/(?P<slug>[\w_-]+)/$', views.ViewCat.as_view(), name='view_cat'), |
16 | 16 | url(r'^categories/delete/(?P<slug>[\w_-]+)/$', views.DeleteCatView.as_view(), name='delete_cat'), |
17 | 17 | url(r'^subjects/(?P<slug>[\w_-]+)/$', views.SubjectsView.as_view(), name='view_subject'), |
18 | - url(r'^topics/create/(?P<slug>[\w_-]+)/$', views.CreateTopicView.as_view(), name='create_topic'), | |
19 | - url(r'^topics/update/(?P<slug>[\w_-]+)/$', views.UpdateTopicView.as_view(), name='update_topic'), | |
20 | 18 | url(r'^subjects/create/(?P<slug>[\w_-]+)/$', views.CreateSubjectView.as_view(), name='create_subject'), |
21 | 19 | url(r'^subjects/update/(?P<slug>[\w_-]+)/$', views.UpdateSubjectView.as_view(), name='update_subject'), |
22 | 20 | url(r'^subjects/delete/(?P<slug>[\w_-]+)/$', views.DeleteSubjectView.as_view(), name='delete_subject'), |
21 | + url(r'^topics/create/(?P<slug>[\w_-]+)/$', views.CreateTopicView.as_view(), name='create_topic'), | |
22 | + url(r'^topics/update/(?P<slug>[\w_-]+)/$', views.UpdateTopicView.as_view(), name='update_topic'), | |
23 | + url(r'^topics/(?P<slug>[\w_-]+)/$', views.TopicsView.as_view(), name='view_topic') | |
23 | 24 | ] | ... | ... |
courses/views.py
... | ... | @@ -12,10 +12,11 @@ from rolepermissions.verifications import has_role |
12 | 12 | from django.db.models import Q |
13 | 13 | from rolepermissions.verifications import has_object_permission |
14 | 14 | |
15 | -from .forms import CourseForm, CategoryForm, SubjectForm,TopicForm | |
15 | +from .forms import CourseForm, UpdateCourseForm, CategoryForm, SubjectForm,TopicForm | |
16 | 16 | from .models import Course, Subject, Category,Topic |
17 | 17 | from core.mixins import NotificationMixin |
18 | 18 | |
19 | +from datetime import date | |
19 | 20 | |
20 | 21 | class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView): |
21 | 22 | |
... | ... | @@ -32,7 +33,7 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView): |
32 | 33 | |
33 | 34 | return context |
34 | 35 | |
35 | -class CreateView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edit.CreateView): | |
36 | +class CreateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edit.CreateView): | |
36 | 37 | |
37 | 38 | allowed_roles = ['professor', 'system_admin'] |
38 | 39 | login_url = reverse_lazy("core:home") |
... | ... | @@ -47,8 +48,6 @@ class CreateView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edi |
47 | 48 | self.object.save() |
48 | 49 | messages.success(self.request, _('Course created successfully!')) |
49 | 50 | |
50 | - return super(CreateView, self).form_valid(form) | |
51 | - | |
52 | 51 | def form_invalid(self, form): |
53 | 52 | print(form) |
54 | 53 | return self.render_to_response(self.get_context_data(form=form)) |
... | ... | @@ -56,27 +55,80 @@ class CreateView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edi |
56 | 55 | def render_to_responssse(self, context, **response_kwargs): |
57 | 56 | return self.response_class(request=self.request, template=self.get_template_names(), context=context, using=self.template_engine) |
58 | 57 | |
59 | -class UpdateView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): | |
58 | + def get_context_data(self, **kwargs): | |
59 | + context = super(CreateCourseView, self).get_context_data(**kwargs) | |
60 | + | |
61 | + if has_role(self.request.user,'system_admin'): | |
62 | + courses = Course.objects.all() | |
63 | + elif has_role(self.request.user,'professor'): | |
64 | + courses = self.request.user.courses.all() | |
65 | + context['courses'] = courses | |
66 | + context['title'] = _("Create Course") | |
67 | + context['now'] = date.today() | |
68 | + return context | |
69 | + | |
70 | +class UpdateCourseView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): | |
60 | 71 | |
61 | 72 | allowed_roles = ['professor', 'system_admin'] |
62 | 73 | login_url = reverse_lazy("core:home") |
63 | 74 | redirect_field_name = 'next' |
64 | 75 | template_name = 'course/update.html' |
65 | 76 | model = Course |
66 | - form_class = CourseForm | |
77 | + form_class = UpdateCourseForm | |
78 | + | |
79 | + def dispatch(self, *args, **kwargs): | |
80 | + course = get_object_or_404(Course, slug = self.kwargs.get('slug')) | |
81 | + if(not has_object_permission('update_course', self.request.user, course)): | |
82 | + return self.handle_no_permission() | |
83 | + return super(UpdateCourseView, self).dispatch(*args, **kwargs) | |
84 | + | |
85 | + def get_context_data(self, **kwargs): | |
86 | + context = super(UpdateCourseView, self).get_context_data(**kwargs) | |
87 | + course = get_object_or_404(Course, slug = self.kwargs.get('slug')) | |
88 | + | |
89 | + if has_role(self.request.user,'system_admin'): | |
90 | + courses = Course.objects.all() | |
91 | + elif has_role(self.request.user,'professor'): | |
92 | + courses = self.request.user.courses.all() | |
93 | + context['courses'] = courses | |
94 | + context['title'] = course.name | |
95 | + context['now'] = date.today() | |
96 | + return context | |
97 | + | |
98 | + def get_success_url(self): | |
99 | + return reverse_lazy('course:view', kwargs={'slug' : self.object.slug}) | |
100 | + | |
101 | + | |
102 | + | |
103 | +class DeleteCourseView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): | |
104 | + | |
105 | + allowed_roles = ['professor', 'system_admin'] | |
106 | + login_url = reverse_lazy("core:home") | |
107 | + redirect_field_name = 'next' | |
108 | + model = Course | |
109 | + template_name = 'course/delete.html' | |
67 | 110 | success_url = reverse_lazy('course:manage') |
68 | 111 | |
69 | - def form_valid(self, form): | |
70 | - self.object = form.save(commit = False) | |
71 | - self.object.slug = slugify(self.object.name) | |
72 | - self.object.save() | |
112 | + def dispatch(self, *args, **kwargs): | |
113 | + course = get_object_or_404(Course, slug = self.kwargs.get('slug')) | |
114 | + if(not has_object_permission('delete_course', self.request.user, course)): | |
115 | + return self.handle_no_permission() | |
116 | + return super(DeleteCourseView, self).dispatch(*args, **kwargs) | |
73 | 117 | |
74 | - return super(UpdateView, self).form_valid(form) | |
118 | + def get_context_data(self, **kwargs): | |
119 | + context = super(DeleteCourseView, self).get_context_data(**kwargs) | |
120 | + course = get_object_or_404(Course, slug = self.kwargs.get('slug')) | |
75 | 121 | |
76 | - def render_to_response(self, context, **response_kwargs): | |
77 | - messages.success(self.request, _('Course edited successfully!')) | |
122 | + if has_role(self.request.user,'system_admin'): | |
123 | + courses = Course.objects.all() | |
124 | + elif has_role(self.request.user,'professor'): | |
125 | + courses = self.request.user.courses.all() | |
126 | + context['courses'] = courses | |
127 | + print (courses,"jdhksjbjs") | |
128 | + context['title'] = course.name | |
129 | + | |
130 | + return context | |
78 | 131 | |
79 | - return self.response_class(request=self.request, template=self.get_template_names(), context=context, using=self.template_engine) | |
80 | 132 | |
81 | 133 | class CourseView(LoginRequiredMixin, NotificationMixin, generic.DetailView): |
82 | 134 | |
... | ... | @@ -90,7 +142,7 @@ class CourseView(LoginRequiredMixin, NotificationMixin, generic.DetailView): |
90 | 142 | context = super(CourseView, self).get_context_data(**kwargs) |
91 | 143 | course = get_object_or_404(Course, slug = self.kwargs.get('slug')) |
92 | 144 | if has_role(self.request.user,'system_admin'): |
93 | - subjects = Subject.objects.all() | |
145 | + subjects = course.subjects.all() | |
94 | 146 | elif has_role(self.request.user,'professor'): |
95 | 147 | subjects = course.subjects.filter(professors__in=[self.request.user]) |
96 | 148 | elif has_role(self.request.user, 'student'): |
... | ... | @@ -239,6 +291,29 @@ class SubjectsView(LoginRequiredMixin, generic.ListView): |
239 | 291 | context['topics'] = subject.topics.all() |
240 | 292 | return context |
241 | 293 | |
294 | +class TopicsView(LoginRequiredMixin, generic.ListView): | |
295 | + | |
296 | + login_url = reverse_lazy("core:home") | |
297 | + redirect_field_name = 'next' | |
298 | + template_name = 'topic/index.html' | |
299 | + context_object_name = 'topics' | |
300 | + model = Topic | |
301 | + | |
302 | + def get_queryset(self): | |
303 | + topic = get_object_or_404(Topic, slug = self.kwargs.get('slug')) | |
304 | + subject = topic.subject | |
305 | + context = subject.topics.filter(visible=True) | |
306 | + #if (self.request.user in subject.professors.all() or has_role(self.request.user,'system_admin')): | |
307 | + #context = subject.topics.all() <- Change it By Activities | |
308 | + return context | |
309 | + | |
310 | + def get_context_data(self, **kwargs): | |
311 | + topic = get_object_or_404(Topic, slug = self.kwargs.get('slug')) | |
312 | + context = super(TopicsView, self).get_context_data(**kwargs) | |
313 | + context['topic'] = topic | |
314 | + context['subject'] = topic.subject | |
315 | + return context | |
316 | + | |
242 | 317 | class CreateTopicView(LoginRequiredMixin, HasRoleMixin, NotificationMixin, generic.edit.CreateView): |
243 | 318 | |
244 | 319 | allowed_roles = ['professor', 'system_admin'] |
... | ... | @@ -386,4 +461,4 @@ class DeleteSubjectView(LoginRequiredMixin, HasRoleMixin, generic.DeleteView): |
386 | 461 | return context |
387 | 462 | |
388 | 463 | def get_success_url(self): |
389 | - return reverse_lazy('course:view_subject', kwargs={'slug' : self.object.course.subjects.all()[0].slug}) | |
464 | + return reverse_lazy('course:view', kwargs={'slug' : self.object.course.slug}) | ... | ... |
users/admin.py
1 | 1 | from django.contrib import admin |
2 | 2 | from .models import User |
3 | -from .forms import ProfileForm | |
3 | +from .forms import UserForm | |
4 | 4 | |
5 | 5 | class UserAdmin(admin.ModelAdmin): |
6 | 6 | list_display = ['username', 'name', 'email', 'is_staff', 'is_active'] |
7 | 7 | search_fields = ['username', 'name', 'email'] |
8 | - form = ProfileForm | |
8 | + form = UserForm | |
9 | 9 | |
10 | 10 | admin.site.register(User, UserAdmin) |
11 | 11 | \ No newline at end of file | ... | ... |
users/forms.py
1 | 1 | # coding=utf-8 |
2 | - | |
2 | +import os | |
3 | +from django.conf import settings | |
3 | 4 | from django import forms |
4 | 5 | from django.utils.translation import ugettext_lazy as _ |
6 | +from rolepermissions.shortcuts import assign_role | |
5 | 7 | from .models import User |
6 | 8 | |
7 | 9 | |
... | ... | @@ -25,10 +27,32 @@ class ProfileForm(forms.ModelForm): |
25 | 27 | } |
26 | 28 | |
27 | 29 | class UserForm(forms.ModelForm): |
30 | + def save(self, commit=True): | |
31 | + super(UserForm, self).save(commit=False) | |
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['password']) | |
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 | |
28 | 49 | |
29 | 50 | class Meta: |
30 | 51 | model = User |
31 | - fields = ['username', 'name', 'email', 'birth_date', 'city', 'state', 'gender', 'type_profile', 'cpf', 'phone', 'image', 'is_staff', 'is_active'] | |
52 | + fields = ['username', 'name', 'email', 'password', 'birth_date', 'city', 'state', 'gender', 'type_profile', 'cpf', 'phone', 'image', 'is_staff', 'is_active'] | |
53 | + widgets = { | |
54 | + 'password':forms.PasswordInput | |
55 | + } | |
32 | 56 | |
33 | 57 | class EditUserForm(forms.ModelForm): |
34 | 58 | ... | ... |
... | ... | @@ -0,0 +1,20 @@ |
1 | +# -*- coding: utf-8 -*- | |
2 | +# Generated by Django 1.10 on 2016-09-16 02:34 | |
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 | + ('users', '0012_auto_20160908_1625'), | |
12 | + ] | |
13 | + | |
14 | + operations = [ | |
15 | + migrations.AlterField( | |
16 | + model_name='user', | |
17 | + name='image', | |
18 | + field=models.ImageField(blank=True, upload_to='users/', verbose_name='Image'), | |
19 | + ), | |
20 | + ] | ... | ... |
users/models.py
... | ... | @@ -4,6 +4,7 @@ from django.db import models |
4 | 4 | from django.core import validators |
5 | 5 | from django.utils.translation import ugettext_lazy as _ |
6 | 6 | from django.contrib.auth.models import AbstractBaseUser, UserManager, PermissionsMixin |
7 | +from django.contrib.staticfiles.templatetags.staticfiles import static | |
7 | 8 | |
8 | 9 | class User(AbstractBaseUser, PermissionsMixin): |
9 | 10 | |
... | ... | @@ -19,7 +20,7 @@ class User(AbstractBaseUser, PermissionsMixin): |
19 | 20 | city = models.CharField(_('City'), max_length = 90, blank = True) |
20 | 21 | state = models.CharField(_('State'), max_length = 30, blank = True) |
21 | 22 | gender = models.CharField(_('Gender'), max_length = 1, choices = (('M', _('Male')), ('F', _('Female')))) |
22 | - image = models.ImageField(verbose_name = _('Image'), blank = True, upload_to = 'users/', default = 'no_image.jpg') | |
23 | + image = models.ImageField(verbose_name = _('Image'), blank = True, upload_to = 'users/') | |
23 | 24 | birth_date = models.DateField(_('Birth Date'), null = True, blank = True) |
24 | 25 | phone = models.CharField(_('Phone'), max_length = 30, blank = True) |
25 | 26 | cpf = models.CharField(_('Cpf'), max_length = 15, blank = True) |
... | ... | @@ -40,8 +41,15 @@ class User(AbstractBaseUser, PermissionsMixin): |
40 | 41 | def __str__(self): |
41 | 42 | return self.name or self.username |
42 | 43 | |
43 | - def det_full_name(self): | |
44 | + def get_full_name(self): | |
44 | 45 | return str(self) |
45 | 46 | |
46 | 47 | def get_short_name(self): |
47 | - return str(self).split(" ")[0] | |
48 | 48 | \ No newline at end of file |
49 | + return str(self).split(" ")[0] | |
50 | + | |
51 | + @property | |
52 | + def image_url(self): | |
53 | + if self.image and hasattr(self.image, 'url'): | |
54 | + return self.image.url | |
55 | + else: | |
56 | + return static('img/no_image.jpg') | |
49 | 57 | \ No newline at end of file | ... | ... |
users/templates/list_users.html
1 | -{% extends 'base.html' %} | |
1 | +{% extends 'home.html' %} | |
2 | 2 | |
3 | -{% load i18n pagination %} | |
3 | +{% load i18n pagination django_bootstrap_breadcrumbs %} | |
4 | 4 | |
5 | 5 | {% block breadcrumbs %} |
6 | - <div class="row"> | |
7 | - <div class="col-md-12"> | |
8 | - <ul class="breadcrumb" style="margin-bottom: 5px;"> | |
9 | - <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> | |
10 | - <li class="active">{% trans 'Manage Users' %}</li> | |
11 | - </ul> | |
12 | - </div> | |
13 | - </div> | |
6 | + | |
7 | + {{ block.super }} | |
8 | + {% breadcrumb 'Manage Users' 'users:manage' %} | |
9 | + | |
14 | 10 | {% endblock %} |
15 | 11 | |
16 | 12 | {% block sidebar %} |
... | ... | @@ -52,7 +48,7 @@ |
52 | 48 | <p>{% trans 'Email' %}: {{ acc.email }}</p> |
53 | 49 | <p>{% trans 'Contact' %}: {{ acc.phone }}</p> |
54 | 50 | <div align="right"> |
55 | - <a href="javascript:void(0)" class="btn btn-raised btn-success">{% trans 'Edit' %}</a> | |
51 | + <a href="{% url 'users:update' acc.username %}" class="btn btn-raised btn-success">{% trans 'Edit' %}</a> | |
56 | 52 | <a href="javascript:void(0)" class="btn btn-raised btn-primary">{% trans 'Delete' %}</a> |
57 | 53 | </div> |
58 | 54 | </div> |
... | ... | @@ -68,3 +64,6 @@ |
68 | 64 | </div> |
69 | 65 | {% endif %} |
70 | 66 | {% endblock %} |
67 | + | |
68 | +{% block rightbar %} | |
69 | +{% endblock rightbar %} | ... | ... |
users/templates/users/create.html
1 | -{% extends 'app/base.html' %} | |
1 | +{% extends 'list_users.html' %} | |
2 | 2 | |
3 | 3 | {% load static i18n %} |
4 | 4 | {% load widget_tweaks %} |
5 | 5 | |
6 | +{% load django_bootstrap_breadcrumbs %} | |
7 | + | |
6 | 8 | {% block breadcrumbs %} |
7 | - <ol class="breadcrumb"> | |
8 | - <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> | |
9 | - <li class="active">{% trans 'New User' %}</li> | |
10 | - </ol> | |
11 | -{% endblock %} | |
12 | 9 | |
13 | -{% block sidebar %} | |
14 | - <div class="list-group"> | |
15 | - <a href="{% url 'users:manage' %}" class="list-group-item"> | |
16 | - {% trans 'System Users' %} | |
17 | - </a> | |
18 | - <a href="{% url 'users:create' %}" class="list-group-item active"> | |
19 | - {% trans 'New Account' %} | |
20 | - </a> | |
21 | - <a href="#" class="list-group-item"> | |
22 | - {% trans 'Send Mail' %} | |
23 | - </a> | |
24 | - </div> | |
10 | + {{ block.super }} | |
11 | + {% breadcrumb 'Add User' 'users:create' %} | |
12 | + | |
25 | 13 | {% endblock %} |
26 | 14 | |
15 | + | |
27 | 16 | {% block content %} |
28 | - <div class="alert alert-info alert-dismissible" role="alert"> | |
29 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
30 | - <span aria-hidden="true">×</span> | |
31 | - </button> | |
32 | - <p>{% trans 'All fields are required' %}</p> | |
33 | - </div> | |
17 | + {% if messages %} | |
18 | + {% for message in messages %} | |
19 | + <div class="alert alert-success alert-dismissible" role="alert"> | |
20 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
21 | + <span aria-hidden="true">×</span> | |
22 | + </button> | |
23 | + <p>{{ message }}</p> | |
24 | + </div> | |
25 | + {% endfor %} | |
26 | + {% endif %} | |
34 | 27 | |
35 | - <form method="post" action="" enctype="multipart/form-data"> | |
36 | - {% csrf_token %} | |
37 | - {% for field in form %} | |
38 | - <div class="form-group{% if form.has_error %} has-error {% endif %}"> | |
39 | - <label for="{{ field.auto_id }}">{{ field.label }}</label> | |
40 | - {% render_field field class='form-control input-sm' %} | |
41 | - <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
42 | - {% if field.errors.length > 0 %} | |
43 | - <div class="alert alert-danger alert-dismissible" role="alert"> | |
44 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
45 | - <span aria-hidden="true">×</span> | |
46 | - </button> | |
47 | - <ul> | |
48 | - {% for error in field.errors %} | |
49 | - <li>{{ error }}</li> | |
50 | - {% endfor %} | |
51 | - </ul> | |
28 | + <div class="card"> | |
29 | + <div class="card-content"> | |
30 | + <div class="card-body"> | |
31 | + <form method="post" action="" enctype="multipart/form-data"> | |
32 | + {% csrf_token %} | |
33 | + {% for field in form %} | |
34 | + <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput"> | |
35 | + <label for="{{ field.auto_id }}">{{ field.label }}</label> | |
36 | + {% if field.auto_id == 'id_birth_date' %} | |
37 | + {% render_field field class='form-control input-sm' type='date' %} | |
38 | + <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
39 | + {% elif field.auto_id == 'id_image' %} | |
40 | + {% render_field field class='form-control input-sm' %} | |
41 | + <div class="input-group"> | |
42 | + <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your photo...' %}"> | |
43 | + <span class="input-group-btn input-group-sm"> | |
44 | + <button type="button" class="btn btn-fab btn-fab-mini"> | |
45 | + <i class="material-icons">attach_file</i> | |
46 | + </button> | |
47 | + </span> | |
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> | |
55 | + {% else %} | |
56 | + {% render_field field class='form-control input-sm' %} | |
57 | + <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
58 | + {% endif %} | |
59 | + {% if field.errors.length > 0 %} | |
60 | + <div class="alert alert-danger alert-dismissible" role="alert"> | |
61 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
62 | + <span aria-hidden="true">×</span> | |
63 | + </button> | |
64 | + <ul> | |
65 | + {% for error in field.errors %} | |
66 | + <li>{{ error }}</li> | |
67 | + {% endfor %} | |
68 | + </ul> | |
69 | + </div> | |
70 | + </div> | |
71 | + {% endif %} | |
72 | + </div> | |
73 | + {% endfor %} | |
74 | + <div class="col-md-offset-2 col-md-2 col-sm-2 col-xs-2"> | |
75 | + <input type="submit" value="{% trans 'Save' %}" class="btn btn-sm btn-success" /> | |
76 | + </div> | |
77 | + <div class="col-md-offset-3 col-md-2 col-sm-2 col-xs-2"> | |
78 | + <a href="{% url 'users:manage' %}" class="btn btn-sm btn-success" >{% trans 'Cancel' %}</a> | |
52 | 79 | </div> |
53 | - </div> | |
54 | - {% endif %} | |
80 | + </form> | |
55 | 81 | </div> |
56 | - {% endfor %} | |
57 | - <input type="submit" value="{% trans 'Save' %}" class="btn btn-sm btn-success" /> | |
58 | - </form> | |
82 | + </div> | |
83 | + </div> | |
84 | + | |
59 | 85 | <br clear="all" /> |
60 | 86 | {% endblock %} | ... | ... |
users/templates/users/update.html
1 | -{% extends 'app/base.html' %} | |
1 | +{% extends 'list_users.html' %} | |
2 | 2 | |
3 | 3 | {% load static i18n %} |
4 | 4 | {% load widget_tweaks %} |
5 | 5 | |
6 | +{% load django_bootstrap_breadcrumbs %} | |
7 | + | |
6 | 8 | {% block breadcrumbs %} |
7 | - <ol class="breadcrumb"> | |
8 | - <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li> | |
9 | - <li class="active">{% trans 'Edit user' %}</li> | |
10 | - </ol> | |
11 | -{% endblock %} | |
12 | 9 | |
13 | -{% block sidebar %} | |
14 | - <div class="list-group"> | |
15 | - <a href="{% url 'users:manage' %}" class="list-group-item"> | |
16 | - {% trans 'System Users' %} | |
17 | - </a> | |
18 | - <a href="{% url 'users:create' %}" class="list-group-item"> | |
19 | - {% trans 'New Account' %} | |
20 | - </a> | |
21 | - <a href="#" class="list-group-item"> | |
22 | - {% trans 'Send Mail' %} | |
23 | - </a> | |
24 | - </div> | |
10 | + {{ block.super }} | |
11 | + {% breadcrumb 'Update User' 'users:update' %} | |
12 | + | |
25 | 13 | {% endblock %} |
26 | 14 | |
15 | + | |
27 | 16 | {% block content %} |
28 | - <div class="alert alert-info alert-dismissible" role="alert"> | |
29 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
30 | - <span aria-hidden="true">×</span> | |
31 | - </button> | |
32 | - <p>{% trans 'All fields are required' %}</p> | |
33 | - </div> | |
17 | + {% if messages %} | |
18 | + {% for message in messages %} | |
19 | + <div class="alert alert-success alert-dismissible" role="alert"> | |
20 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
21 | + <span aria-hidden="true">×</span> | |
22 | + </button> | |
23 | + <p>{{ message }}</p> | |
24 | + </div> | |
25 | + {% endfor %} | |
26 | + {% endif %} | |
34 | 27 | |
35 | - <form method="post" action="" enctype="multipart/form-data"> | |
36 | - {% csrf_token %} | |
37 | - {% for field in form %} | |
38 | - <div class="form-group{% if form.has_error %} has-error {% endif %}"> | |
39 | - <label for="{{ field.auto_id }}">{{ field.label }}</label> | |
40 | - {% render_field field class='form-control input-sm' %} | |
41 | - <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
42 | - {% if field.errors.length > 0 %} | |
43 | - <div class="alert alert-danger alert-dismissible" role="alert"> | |
44 | - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
45 | - <span aria-hidden="true">×</span> | |
46 | - </button> | |
47 | - <ul> | |
48 | - {% for error in field.errors %} | |
49 | - <li>{{ error }}</li> | |
50 | - {% endfor %} | |
51 | - </ul> | |
28 | + <div class="card"> | |
29 | + <div class="card-content"> | |
30 | + <div class="card-body"> | |
31 | + <form method="post" action="" enctype="multipart/form-data"> | |
32 | + {% csrf_token %} | |
33 | + {% for field in form %} | |
34 | + <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput"> | |
35 | + <label for="{{ field.auto_id }}">{{ field.label }}</label> | |
36 | + {% if field.auto_id == 'id_birth_date' %} | |
37 | + {% render_field field class='form-control input-sm' type='date' %} | |
38 | + <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
39 | + {% elif field.auto_id == 'id_image' %} | |
40 | + {% render_field field class='form-control input-sm' %} | |
41 | + <div class="input-group"> | |
42 | + <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your photo...' %}"> | |
43 | + <span class="input-group-btn input-group-sm"> | |
44 | + <button type="button" class="btn btn-fab btn-fab-mini"> | |
45 | + <i class="material-icons">attach_file</i> | |
46 | + </button> | |
47 | + </span> | |
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> | |
55 | + {% else %} | |
56 | + {% render_field field class='form-control input-sm' %} | |
57 | + <span id="helpBlock" class="help-block">{{ field.help_text }}</span> | |
58 | + {% endif %} | |
59 | + {% if field.errors.length > 0 %} | |
60 | + <div class="alert alert-danger alert-dismissible" role="alert"> | |
61 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
62 | + <span aria-hidden="true">×</span> | |
63 | + </button> | |
64 | + <ul> | |
65 | + {% for error in field.errors %} | |
66 | + <li>{{ error }}</li> | |
67 | + {% endfor %} | |
68 | + </ul> | |
69 | + </div> | |
70 | + </div> | |
71 | + {% endif %} | |
72 | + </div> | |
73 | + {% endfor %} | |
74 | + <div class="col-md-offset-2 col-md-2 col-sm-2 col-xs-2"> | |
75 | + <input type="submit" value="{% trans 'Save' %}" class="btn btn-sm btn-success" /> | |
76 | + </div> | |
77 | + <div class="col-md-offset-3 col-md-2 col-sm-2 col-xs-2"> | |
78 | + <a href="{% url 'users:manage' %}" class="btn btn-sm btn-success" >{% trans 'Cancel' %}</a> | |
52 | 79 | </div> |
53 | - </div> | |
54 | - {% endif %} | |
80 | + </form> | |
55 | 81 | </div> |
56 | - {% endfor %} | |
57 | - <input type="submit" value="{% trans 'Save' %}" class="btn btn-sm btn-success" /> | |
58 | - </form> | |
82 | + </div> | |
83 | + </div> | |
59 | 84 | <br clear="all" /> |
60 | 85 | {% endblock %} | ... | ... |