Commit 4d667d767733936f7883d6a1790af5e56f479a98

Authored by Matheus Lins
2 parents 7eb01551 131b2f1c

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

amadeus/local_settings.py.example
... ... @@ -1,16 +0,0 @@
1   -import os
2   -
3   -DEBUG = True
4   -
5   -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
6   -
7   -DATABASES = {
8   - 'default': {
9   - 'ENGINE': 'django.db.backends.postgresql',
10   - 'NAME': 'amadeus',
11   - 'USER': 'amadeus_admin',
12   - 'PASSWORD': 'amadeus',
13   - 'HOST': '127.0.0.1',
14   - 'PORT': '5432',
15   - }
16   -}
17 0 \ No newline at end of file
amadeus/settings.py
... ... @@ -55,7 +55,8 @@ INSTALLED_APPS = [
55 55 'courses',
56 56 'forum',
57 57 'poll',
58   - 'avaliacao',
  58 + 'links',
  59 + 'exam',
59 60  
60 61 ]
61 62  
... ...
avaliacao/__init__.py
avaliacao/admin.py
... ... @@ -1,3 +0,0 @@
1   -from django.contrib import admin
2   -
3   -# Register your models here.
avaliacao/apps.py
... ... @@ -1,5 +0,0 @@
1   -from django.apps import AppConfig
2   -
3   -
4   -class AvaliacaoConfig(AppConfig):
5   - name = 'avaliacao'
avaliacao/migrations/__init__.py
avaliacao/models.py
... ... @@ -1,20 +0,0 @@
1   -from django.utils.translation import ugettext_lazy as _
2   -from django.db import models
3   -from autoslug.fields import AutoSlugField
4   -from users.models import User
5   -from core.models import Resource
6   -from courses.models import Activity
7   -
8   -class Avaliacao(Activity):
9   -
10   - name_avalicao = models.CharField(_('Name'), max_length = 100)
11   - init_date = models.DateField(_('Begin of Avaliacao Date'))
12   - end_date = models.DateField(_('End of Avaliacao Date'))
13   -
14   - class Meta:
15   - #ordering = ('create_date','name')
16   - verbose_name = _('Avaliacao')
17   - verbose_name_plural = _('Avaliacoes')
18   -
19   -def __str__(self):
20   - return str(self.name) + str("/") + str(self.topic)
avaliacao/tests.py
... ... @@ -1,3 +0,0 @@
1   -from django.test import TestCase
2   -
3   -# Create your tests here.
avaliacao/urls.py
... ... @@ -1,7 +0,0 @@
1   -from django.conf.urls import url
2   -
3   -from . import views
4   -
5   -urlpatterns =[
6   -
7   -]
avaliacao/views.py
... ... @@ -1,3 +0,0 @@
1   -from django.shortcuts import render
2   -
3   -# Create your views here.
courses/urls.py
... ... @@ -26,5 +26,4 @@ urlpatterns = [
26 26  
27 27 url(r'^forum/', include('forum.urls', namespace = 'forum')),
28 28 url(r'^poll/', include('poll.urls', namespace = 'poll')),
29   - url(r'^avaliacao/', include('avaliacao.urls', namespace = 'avaliacao'))
30 29 ]
... ...
courses/views.py
... ... @@ -292,7 +292,7 @@ class TopicsView(LoginRequiredMixin, generic.ListView):
292 292 topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
293 293 context = super(TopicsView, self).get_context_data(**kwargs)
294 294 activitys = Activity.objects.filter(topic__name = topic.name)
295   - students_activit = User.objects.filter(activities = Activity.objects.all())
  295 + students_activit = User.objects.filter(activities__in = Activity.objects.all())
296 296 # page_user = User.objects.get(id= self.kwargs['user_id'])
297 297 context['topic'] = topic
298 298 context['subject'] = topic.subject
... ...
exam/__init__.py 0 → 100644
exam/admin.py 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +from django.contrib import admin
  2 +
  3 +# Register your models here.
... ...
exam/apps.py 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +from django.apps import AppConfig
  2 +
  3 +
  4 +class ExamConfig(AppConfig):
  5 + name = 'exam'
... ...
exam/forms.py 0 → 100644
... ... @@ -0,0 +1,39 @@
  1 +from django import forms
  2 +from .models import Exam
  3 +
  4 +class ExamForm(forms.ModelForm):
  5 + def clean_end_date(self):
  6 + beginDate = self.data['beginDate']
  7 + endDate = self.data['endDate']
  8 +
  9 + if beginDate and endDate and endDate < beginDate:
  10 + raise forms.ValidationError(_('The end date may not be before the start date.'))
  11 + return endDate
  12 +
  13 + def clean_begin_date(self):
  14 + endDate = self.data['endDate']
  15 + beginDate = self.data['beginDate']
  16 +
  17 + if enDate and benginDate and beginDate <= endDate:
  18 + raise forms.ValidationError(_('The exam start date must be after the end of registration.'))
  19 + return beginDate
  20 +
  21 + def clean_end_date(self):
  22 + beginDate = self.data['beginDate']
  23 + endDate = self.data['endDate']
  24 +
  25 + if beginDate and endDate and endDate < beginDate:
  26 + raise forms.ValidationError(_('The finish date may not be before the start date.'))
  27 + return end_date
  28 +
  29 +
  30 +
  31 + class Meta:
  32 + model = Exam
  33 + fields = ['name','beginDate','endDate']
  34 +
  35 + widgets = {
  36 + 'name': forms.TextInput(attrs={'placeholder': 'Exam?'}),
  37 + 'beginDate': forms.DateTimeInput(attrs={'placeholder': 'Start date to resolve the exam'}),
  38 + 'endDate': forms.DateTimeInput(attrs={'placeholder': 'Finish date permited to resolve the exam'}),
  39 + }
... ...
exam/migrations/0001_initial.py 0 → 100644
... ... @@ -0,0 +1,48 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-10-06 19:57
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.db import migrations, models
  6 +import django.db.models.deletion
  7 +
  8 +
  9 +class Migration(migrations.Migration):
  10 +
  11 + initial = True
  12 +
  13 + dependencies = [
  14 + ]
  15 +
  16 + operations = [
  17 + migrations.CreateModel(
  18 + name='Answer',
  19 + fields=[
  20 + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
  21 + ('answer', models.CharField(max_length=200, verbose_name='Answer')),
  22 + ('order', models.PositiveSmallIntegerField(verbose_name='Order')),
  23 + ],
  24 + options={
  25 + 'verbose_name_plural': 'Answers',
  26 + 'ordering': ('order',),
  27 + 'verbose_name': 'Answer',
  28 + },
  29 + ),
  30 + migrations.CreateModel(
  31 + name='Exam',
  32 + fields=[
  33 + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
  34 + ('name', models.CharField(max_length=100, verbose_name='Name')),
  35 + ('beginDate', models.DateTimeField(auto_now_add=True, verbose_name='Start Date')),
  36 + ('endDate', models.DateTimeField(auto_now=True, verbose_name='Date of last update')),
  37 + ],
  38 + options={
  39 + 'verbose_name_plural': 'Exams',
  40 + 'verbose_name': 'Exam',
  41 + },
  42 + ),
  43 + migrations.AddField(
  44 + model_name='answer',
  45 + name='exam',
  46 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='exam.Exam', verbose_name='Answers'),
  47 + ),
  48 + ]
... ...
exam/migrations/__init__.py 0 → 100644
exam/models.py 0 → 100644
... ... @@ -0,0 +1,34 @@
  1 +from django.utils.translation import ugettext_lazy as _
  2 +from django.db import models
  3 +from autoslug.fields import AutoSlugField
  4 +from users.models import User
  5 +from core.models import Resource
  6 +from courses.models import Activity
  7 +
  8 +
  9 +
  10 +class Exam(models.Model):
  11 + name = models.CharField(_('Name'), max_length = 100)
  12 + beginDate = models.DateTimeField(_('Start Date'), auto_now_add = True)
  13 + endDate = models.DateTimeField(_('Date of last update'), auto_now=True)
  14 +
  15 + class Meta:
  16 + #ordering = ('create_date','name')
  17 + verbose_name = _('Exam')
  18 + verbose_name_plural = _('Exams')
  19 +
  20 + def __str__(self):
  21 + return str(self.name) + str("/") + str(self.topic)
  22 +
  23 +class Answer(models.Model):
  24 + answer = models.CharField(_("Answer"), max_length = 200)
  25 + order = models.PositiveSmallIntegerField(_("Order"))
  26 + exam = models.ForeignKey(Exam, verbose_name = _('Answers'), related_name='answers')
  27 +
  28 + class Meta:
  29 + ordering = ('order',)
  30 + verbose_name = _('Answer')
  31 + verbose_name_plural = _('Answers')
  32 +
  33 + def __str__(self):
  34 + return str(self.answer) + str("/") + str(self.poll)
... ...
exam/permisissions.py 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +from rolepermissions.permissions import register_object_checker
  2 +from amadeus.roles import SystemAdmin
  3 +
  4 +@register_object_checker()
  5 +def edit_exam(role, user, exam):
  6 + if (role == SystemAdmin):
  7 + return True
  8 +
  9 + if (user in exam.topic.subject.professors.all()):
  10 + return True
  11 +
  12 + return False
... ...
exam/templatetags/__init__.py 0 → 100644
exam/templatetags/dict_access.py 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +from django import template
  2 +
  3 +from forum.models import Forum
  4 +
  5 +register = template.Library()
  6 +
  7 +"""
  8 + Template tag to load all the foruns of a post
  9 +"""
  10 +
  11 +@register.filter
  12 +def value(dictionary, key):
  13 + return dictionary[key]
... ...
exam/tests.py 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +from django.test import TestCase
  2 +
  3 +# Create your tests here.
... ...
exam/urls.py 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +from django.conf.urls import url
  2 +
  3 +from . import views
  4 +
  5 +urlpatterns = [
  6 + url(r'^create/(?P<slug>[\w\-_]+)/$', views.CreateExam.as_view(), name='create_poll'),
  7 + url(r'^update/(?P<slug>[\w\-_]+)/$', views.UpdateExam.as_view(), name='update_poll'),
  8 +
  9 +]
... ...
exam/views.py 0 → 100644
... ... @@ -0,0 +1,97 @@
  1 +from django.shortcuts import render, get_object_or_404, redirect
  2 +from django.views import generic
  3 +from django.contrib.auth.decorators import login_required
  4 +from django.core.paginator import Paginator, EmptyPage
  5 +from django.contrib.auth.mixins import LoginRequiredMixin
  6 +from rolepermissions.mixins import HasRoleMixin
  7 +from django.core.urlresolvers import reverse_lazy
  8 +from django.utils.translation import ugettext_lazy as _
  9 +from rolepermissions.verifications import has_role
  10 +from rolepermissions.verifications import has_object_permission
  11 +# from django.views.generic.edit import FormMixin
  12 +
  13 +from .forms import ExamForm
  14 +from .models import Exam, Answer
  15 +from core.mixins import NotificationMixin
  16 +from users.models import User
  17 +from courses.models import Course, Topic
  18 +
  19 +class CreateExam(LoginRequiredMixin,generic.CreateView):
  20 +
  21 + login_url = reverse_lazy("core:home")
  22 + redirect_field_name = 'next'
  23 + model = Exam
  24 + form_class = PollForm
  25 + context_object_name = 'exam'
  26 + template_name = 'exam/form_exam.html'
  27 + success_url = reverse_lazy('core:home')
  28 +
  29 + def form_valid(self, form):
  30 + self.object = form.save(commit = False)
  31 + topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
  32 + self.object.topic = topic
  33 + self.object.save()
  34 +
  35 + for key in self.request.POST:
  36 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'beginDate' and key != 'endDate'):
  37 + answer = Answer(answer=self.request.POST[key],order=key,poll=self.object)
  38 + answer.save()
  39 +
  40 + return super(CreateExam, self).form_valid(form)
  41 +
  42 + def form_invalid(self, form,**kwargs):
  43 + context = super(CreateExam, self).form_invalid(form)
  44 + answers = {}
  45 + for key in self.request.POST:
  46 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'beginDate' and key != 'endDate'):
  47 + answers[key] = self.request.POST[key]
  48 +
  49 + keys = sorted(answers)
  50 + context.context_data['answers'] = answers
  51 + context.context_data['keys'] = keys
  52 + return context
  53 +
  54 +class UpdateExam(LoginRequiredMixin,generic.UpdateView):
  55 +
  56 + login_url = reverse_lazy("core:home")
  57 + redirect_field_name = 'next'
  58 + model = Exam
  59 + form_class = ExamForm
  60 + context_object_name = 'exam'
  61 + template_name = 'poll/form_exam.html'
  62 + success_url = reverse_lazy('core:home')
  63 +
  64 + def dispatch(self, *args, **kwargs):
  65 + poll = get_object_or_404(Poll, slug = self.kwargs.get('slug'))
  66 +
  67 + if(not has_object_permission('edit_exam', self.request.user, exam)):
  68 + return self.handle_no_permission()
  69 + return super(UpdateExam, self).dispatch(*args, **kwargs)
  70 +
  71 + def get_object(self, queryset=None):
  72 + return get_object_or_404(Poll, slug = self.kwargs.get('slug'))
  73 +
  74 + def form_valid(self, form):
  75 + poll = self.object
  76 + poll = form.save(commit = False)
  77 + poll.answers.all().delete()
  78 + poll.save()
  79 +
  80 + for key in self.request.POST:
  81 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'beginDate' and key != 'endDate'):
  82 + answer = Answer(answer=self.request.POST[key],order=key,exam=exam)
  83 + answer.save()
  84 +
  85 + return super(UpdateExam, self).form_valid(form)
  86 +
  87 + def form_invalid(self, form,**kwargs):
  88 + context = super(UpdateExam, self).form_invalid(form)
  89 + answers = {}
  90 + for key in self.request.POST:
  91 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'beginDate' and key != 'endDate'):
  92 + answers[key] = self.request.POST[key]
  93 +
  94 + keys = sorted(answers)
  95 + context.context_data['answers'] = answers
  96 + context.context_data['keys'] = keys
  97 + return context
... ...
forum/static/js/forum.js
... ... @@ -255,6 +255,49 @@ function answer(id, url) {
255 255  
256 256 /*
257 257 *
  258 +* Function to load form to edit post answer
  259 +*
  260 +*/
  261 +function edit_post_answer(url, answer_id) {
  262 + $.ajax({
  263 + url: url,
  264 + success: function(data) {
  265 + $("#answer_"+answer_id).find(".post_answer_content").hide();
  266 + $("#answer_"+answer_id).find(".post_answer_content").after(data);
  267 +
  268 + var frm = $("#answer_"+answer_id).find(".answer_post_form");
  269 + frm.submit(function () {
  270 + $.ajax({
  271 + type: frm.attr('method'),
  272 + url: frm.attr('action'),
  273 + data: frm.serialize(),
  274 + success: function (data) {
  275 + $("#answer_"+answer_id).parent().after(data);
  276 + frm.parent().parent().remove();
  277 + },
  278 + error: function(data) {
  279 + console.log(frm.serialize());
  280 + console.log('Error');
  281 + }
  282 + });
  283 + return false;
  284 + });
  285 + }
  286 + });
  287 +}
  288 +
  289 +/*
  290 +*
  291 +* Function to cancel post answer edition
  292 +*
  293 +*/
  294 +function cancelEditPostAnswer(answer_id) {
  295 + $("#answer_"+answer_id).find(".post_answer_content").show();
  296 + $("#answer_"+answer_id).find(".answer_post_form").remove();
  297 +}
  298 +
  299 +/*
  300 +*
258 301 * Function to delete an answer
259 302 *
260 303 */
... ...
forum/templates/post/post_update_form.html
1 1 {% load i18n permission_tags list_post %}
2 2 {% load widget_tweaks %}
3 3  
4   -<form class="edit_post_form" method="post" action="{% url 'forum:update_post' post.id %}" enctype="multipart/form-data">
  4 +<form class="edit_post_form" method="post" action="{% url 'course:forum:update_post' post.id %}" enctype="multipart/form-data">
5 5 {% csrf_token %}
6 6 {% for field in form %}
7 7 {% if field.field.widget.input_type == 'hidden' %}
... ...
forum/templates/post_answers/post_answer_form.html
1 1 {% load static i18n %}
2 2 {% load widget_tweaks %}
3 3  
4   -<form class="answer_post_form" method="post" action="{% if answer %}{% else %}{% url 'course:forum:reply_post' %}{% endif %}" enctype="multipart/form-data">
  4 +<form class="answer_post_form" method="post" action="{% if answer %}{% url 'course:forum:update_post_answer' answer.id %}{% else %}{% url 'course:forum:reply_post' %}{% endif %}" enctype="multipart/form-data">
5 5 {% csrf_token %}
6 6 {% for field in form %}
7 7 {% if field.field.widget.input_type == 'hidden' %}
... ... @@ -27,11 +27,18 @@
27 27 </div>
28 28 </div>
29 29 {% endif %}
30   - <span class="input-group-btn">
31   - <button type="submit" class="btn btn-fab btn-fab-mini">
32   - <i class="material-icons">send</i>
33   - </button>
34   - </span>
  30 + {% if answer %}
  31 + <div class="pull-right">
  32 + <button type="button" onclick="cancelEditPostAnswer('{{ answer.id }}')" class="btn btn-danger btn-raised">{% trans 'Cancel' %}</button>
  33 + <button type="submit" class="btn btn-primary btn-raised">{% trans 'Save changes' %}</button>
  34 + </div>
  35 + {% else %}
  36 + <span class="input-group-btn">
  37 + <button type="submit" class="btn btn-fab btn-fab-mini">
  38 + <i class="material-icons">send</i>
  39 + </button>
  40 + </span>
  41 + {% endif %}
35 42 </div>
36 43 </div>
37 44 {% endif %}
... ...
forum/templates/post_answers/post_answer_list.html
... ... @@ -2,28 +2,36 @@
2 2  
3 3 {% if answers|length > 0 %}
4 4 {% for answer in answers %}
5   - <div id="answer_{{ answer.id }}" class="row" style="background-color: #e0e0e0">
6   - <div class="col-sm-12 col-xs-12">
7   - <h3 class="user-name">
8   - {{ answer.user }}
9   - {% if request.user|has_role:'system_admin' or request.user == answer.user %}
10   - <div class="pull-right">
11   - <div class="btn-group icon-more-horiz">
12   - <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
13   - <i class="material-icons">more_horiz</i>
14   - </a>
15   - <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
16   - <li><a href="javascript:void(0)"><i class="material-icons">create</i> {% trans 'Edit' %}</a></li>
17   - <li><a href="javascript:delete_answer('{% url 'course:forum:delete_answer' answer.id %}', '{{ answer.id }}', '{% trans "Are you sure you want to delete this answer?" %}')"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li>
18   - </ul>
  5 + <div>
  6 + <div id="answer_{{ answer.id }}" class="row" style="background-color: #e0e0e0">
  7 + <div class="col-sm-12 col-xs-12">
  8 + <h3 class="user-name">
  9 + {{ answer.user }}
  10 + {% if request.user|has_role:'system_admin' or request.user == answer.user %}
  11 + <div class="pull-right">
  12 + <div class="btn-group icon-more-horiz">
  13 + <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
  14 + <i class="material-icons">more_horiz</i>
  15 + </a>
  16 + <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
  17 + <li><a href="javascript:edit_post_answer('{% url 'course:forum:update_post_answer' answer.id %}', '{{ answer.id }}')"><i class="material-icons">create</i> {% trans 'Edit' %}</a></li>
  18 + <li><a href="javascript:delete_answer('{% url 'course:forum:delete_answer' answer.id %}', '{{ answer.id }}', '{% trans "Are you sure you want to delete this answer?" %}')"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li>
  19 + </ul>
  20 + </div>
19 21 </div>
  22 + {% endif %}
  23 + </h3>
  24 + <div class="post_answer_content">
  25 + <div class="card-data">
  26 + <p class="comment-date"><i class="fa fa-clock-o"></i> {{ answer.answer_date|timesince }} {% trans 'ago' %}
  27 + {% if answer.answer_date != answer.modifiction_date %}
  28 + <em> - {% trans 'Edited' %}</em>
  29 + {% endif %}
  30 + </p>
20 31 </div>
21   - {% endif %}
22   - </h3>
23   - <div class="card-data">
24   - <p class="comment-date"><i class="fa fa-clock-o"></i> {{ answer.answer_date|timesince }} {% trans 'ago' %}</p>
  32 + <p class="comment-text">{{ answer.message|linebreaks }}</p>
  33 + </div>
25 34 </div>
26   - <p class="comment-text">{{ answer.message|linebreaks }}</p>
27 35 </div>
28 36 </div>
29 37 {% endfor %}
... ...
forum/templates/post_answers/post_answer_render.html
1 1 {% load i18n permission_tags %}
2 2  
3   -<div id="answer_{{ answer.id }}" class="row" style="background-color: #e0e0e0">
4   - <div class="col-sm-12 col-xs-12">
5   - <h3 class="user-name">
6   - {{ answer.user }}
7   - {% if request.user|has_role:'system_admin' or request.user == answer.user %}
8   - <div class="pull-right">
9   - <div class="btn-group icon-more-horiz">
10   - <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
11   - <i class="material-icons">more_horiz</i>
12   - </a>
13   - <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
14   - <li><a href="javascript:void(0)"><i class="material-icons">create</i> {% trans 'Edit' %}</a></li>
15   - <li><a href="javascript:delete_answer('{% url 'course:forum:delete_answer' answer.id %}', '{{ answer.id }}', '{% trans "Are you sure you want to delete this answer?" %}')"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li>
16   - </ul>
  3 +<div>
  4 + <div id="answer_{{ answer.id }}" class="row" style="background-color: #e0e0e0">
  5 + <div class="col-sm-12 col-xs-12">
  6 + <h3 class="user-name">
  7 + {{ answer.user }}
  8 + {% if request.user|has_role:'system_admin' or request.user == answer.user %}
  9 + <div class="pull-right">
  10 + <div class="btn-group icon-more-horiz">
  11 + <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
  12 + <i class="material-icons">more_horiz</i>
  13 + </a>
  14 + <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
  15 + <li><a href="javascript:edit_post_answer('{% url 'course:forum:update_post_answer' answer.id %}', '{{ answer.id }}')"><i class="material-icons">create</i> {% trans 'Edit' %}</a></li>
  16 + <li><a href="javascript:delete_answer('{% url 'course:forum:delete_answer' answer.id %}', '{{ answer.id }}', '{% trans "Are you sure you want to delete this answer?" %}')"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li>
  17 + </ul>
  18 + </div>
17 19 </div>
  20 + {% endif %}
  21 + </h3>
  22 + <div class="post_answer_content">
  23 + <div class="card-data">
  24 + <p class="comment-date"><i class="fa fa-clock-o"></i> {{ answer.answer_date|timesince }} {% trans 'ago' %}
  25 + {% if answer.answer_date != answer.modifiction_date %}
  26 + <em> - {% trans 'Edited' %}</em>
  27 + {% endif %}
  28 + </p>
18 29 </div>
19   - {% endif %}
20   - </h3>
21   - <div class="card-data">
22   - <p class="comment-date"><i class="fa fa-clock-o"></i> {{ answer.answer_date|timesince }} {% trans 'ago' %}</p>
  30 + <p class="comment-text">{{ answer.message|linebreaks }}</p>
  31 + </div>
23 32 </div>
24   - <p class="comment-text">{{ answer.message|linebreaks }}</p>
25 33 </div>
26 34 </div>
27 35 \ No newline at end of file
... ...
forum/urls.py
... ... @@ -18,6 +18,7 @@ urlpatterns = [
18 18 url(r'^post_deleted/$', views.post_deleted, name='deleted_post'),
19 19 url(r'^post_answers/$', views.PostAnswerIndex.as_view(), name='post_answers'),
20 20 url(r'^reply_post/$', views.CreatePostAnswerView.as_view(), name='reply_post'),
  21 + url(r'^update_post_answer/(?P<pk>[\w_-]+)/$', views.PostAnswerUpdateView.as_view(), name='update_post_answer'),
21 22 url(r'^render_post_answer/([\w_-]+)/$', views.render_post_answer, name='render_post_answer'),
22 23 url(r'^delete_post_answer/(?P<pk>[\w_-]+)/$', views.PostAnswerDeleteView.as_view(), name='delete_answer'),
23 24 url(r'^post_answer_deleted/$', views.answer_deleted, name='deleted_answer'),
... ...
forum/views.py
... ... @@ -210,6 +210,20 @@ def render_post_answer(request, answer):
210 210  
211 211 return render(request, "post_answers/post_answer_render.html", context)
212 212  
  213 +class PostAnswerUpdateView(LoginRequiredMixin, generic.UpdateView):
  214 + login_url = reverse_lazy("core:home")
  215 + redirect_field_name = 'next'
  216 +
  217 + form_class = PostAnswerForm
  218 + model = PostAnswer
  219 + template_name = "post_answers/post_answer_form.html"
  220 + context_object_name = 'answer'
  221 +
  222 + def get_success_url(self):
  223 + self.success_url = reverse('course:forum:render_post_answer', args = (self.object.id, ))
  224 +
  225 + return self.success_url
  226 +
213 227 class PostAnswerDeleteView(LoginRequiredMixin, generic.DeleteView):
214 228 login_url = reverse_lazy("core:home")
215 229 redirect_field_name = 'next'
... ...
links/models.py
  1 +
1 2 from django.db import models
2 3 from courses.models import Material
3 4 # Create your models here.
4   -class Link(Material,models.Model):
5   - name = models.CharField(max_lenght = 100)
6   - link = models.UrlField()
7   - description = models.CharField(max_lenght = 200)
  5 +class Link(models.Model):
  6 + name = models.CharField(max_length=100)
  7 + link = models.URLField()
  8 + description = models.CharField(max_length=200)
8 9 class Meta:
9 10 verbose_name = 'Link'
10 11 verbose_name_plural = "Links"
11 12 def __str__(self):
12 13 return str(self.name)
13   -
14   -
15   -
... ...
users/templates/users/profile.html
... ... @@ -20,7 +20,7 @@
20 20 <ul class="nav nav-pills nav-stacked">
21 21 <li><a href="{% url 'app:index' %}">{% trans 'Home' %}</a></li>
22 22 <li><a href="{% url 'users:profile' %}">{% trans 'View Profile' %}</a></li>
23   - <li><a href="{% url 'users:edit_profile' user.id %}">{% trans 'Edit Profile' %}</a></li>
  23 + <li><a href="{% url 'users:update_profile' %}">{% trans 'Edit Profile' %}</a></li>
24 24 </ul>
25 25 </div>
26 26 </div>
... ...
users/urls.py
... ... @@ -9,7 +9,6 @@ urlpatterns = [
9 9 url(r'^view/(?P<username>[\w_-]+)/$', views.View.as_view(), name='view'),
10 10 url(r'^delete/(?P<username>[\w_-]+)/$', views.delete, name='delete'),
11 11 url(r'^profile/$', views.Profile.as_view(), name='profile'),
12   - url(r'^profile/editar/(?P<username>[\w_-]+)/$', views.EditProfile.as_view(), name='edit_profile'),
13 12 #
14 13 url(r'^profile/update/$', views.UpdateProfile.as_view(), name='update_profile'),
15 14 url(r'^profile/delete/$', views.DeleteUser.as_view(), name='delete_profile'),
... ...
users/views.py
... ... @@ -142,32 +142,4 @@ class Profile(LoginRequiredMixin, generic.DetailView):
142 142  
143 143 def get_object(self):
144 144 user = get_object_or_404(User, username = self.request.user.username)
145   - return user
146   -
147   -class EditProfile(LoginRequiredMixin, generic.UpdateView):
148   -
149   - login_url = reverse_lazy('core:home')
150   - redirect_field_name = 'next'
151   - template_name = 'users/edit_profile.html'
152   - form_class = UserForm
153   - success_url = reverse_lazy('app:users:edit_profile')
154   -
155   - def get_object(self):
156   - user = get_object_or_404(User, username = self.request.user.username)
157   - return user
158   -
159   - def form_valid(self, form):
160   - self.object = form.save(commit = False)
161   -
162   - if self.object.type_profile == 2:
163   - assign_role(self.object, 'student')
164   - elif self.object.type_profile == 1:
165   - assign_role(self.object, 'professor')
166   - elif self.object.is_staff:
167   - assign_role(self.object, 'system_admin')
168   -
169   - self.object.save()
170   -
171   - messages.success(self.request, _('Profile edited successfully!'))
172   -
173   - return super(EditProfile, self).form_valid(form)
174 145 \ No newline at end of file
  146 + return user
175 147 \ No newline at end of file
... ...