Commit 75162f0f48d8599787eb9e048f114444d19b0b48

Authored by Matheus Lins
2 parents fe3b3af0 841817e1

fixing conflits

amadeus/settings.py
... ... @@ -79,6 +79,7 @@ TEMPLATES = [
79 79 'django.contrib.messages.context_processors.messages',
80 80  
81 81 'core.context_processors.notifications',
  82 + 'courses.context_processors.courses',
82 83 ],
83 84 },
84 85 },
... ...
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  
... ...
core/migrations/0009_auto_20160916_0126.py 0 → 100644
... ... @@ -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 +}
... ...
core/static/img/no_image.jpg 0 → 100644

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">
... ...
courses/context_processors.py 0 → 100644
... ... @@ -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:
... ...
courses/migrations/0013_auto_20160916_0001.py 0 → 100644
... ... @@ -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 + ]
... ...
courses/migrations/0013_auto_20160916_0126.py 0 → 100644
... ... @@ -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 + ]
... ...
courses/migrations/0014_merge_20160916_0255.py 0 → 100644
... ... @@ -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">&times;</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">&times;</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">&times;</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">&times;</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 %}
... ...
courses/templates/topic/index.html 0 → 100644
... ... @@ -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  
... ...
users/migrations/0013_auto_20160915_2334.py 0 → 100644
... ... @@ -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">&times;</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">&times;</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">&times;</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">&times;</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">&times;</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">&times;</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">&times;</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">&times;</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 %}
... ...