From 1add24d1a195e5dfc541d465a730f83dc5ff9fc8 Mon Sep 17 00:00:00 2001 From: janmax <mail-github@jmx.io> Date: Thu, 9 Mar 2017 12:33:22 +0100 Subject: [PATCH] Separated unassigned feedback from feedback list --- core/migrations/0022_auto_20170308_1439.py | 25 +++++++++++ core/models.py | 50 ++++++++++----------- core/templates/base.html | 3 ++ core/templates/core/feedback_form.html | 9 +++- core/templates/core/index.html | 2 +- core/templates/core/student_startpage.html | 17 +++++++ core/templates/core/tutor_startpage.html | 9 +++- core/urls.py | 4 +- core/views.py | 52 ++++++++++++++++------ 9 files changed, 125 insertions(+), 46 deletions(-) create mode 100644 core/migrations/0022_auto_20170308_1439.py create mode 100644 core/templates/core/student_startpage.html diff --git a/core/migrations/0022_auto_20170308_1439.py b/core/migrations/0022_auto_20170308_1439.py new file mode 100644 index 00000000..c67c8c74 --- /dev/null +++ b/core/migrations/0022_auto_20170308_1439.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-03-08 14:39 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0021_auto_20170307_2122'), + ] + + operations = [ + migrations.AddField( + model_name='feedback', + name='final', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='submissionstatus', + name='status', + field=models.PositiveIntegerField(choices=[(0, 'READY'), (1, 'LIMIT_REACHED')], default=0), + ), + ] diff --git a/core/models.py b/core/models.py index 9f3f75ae..bbfba491 100644 --- a/core/models.py +++ b/core/models.py @@ -73,6 +73,12 @@ class Submission(models.Model): self.student ) + def feedback_counter(self): + return self.feedback_list.count() + + def feedback_limit_reached(self): + return self.feedback_counter() == MAX_FEEDBACK_PER_SUBMISSION + @classmethod def assign_tutor(cls, tutor): """Assigns a tutor to a submission @@ -103,16 +109,16 @@ class Submission(models.Model): feedback.save() # set the status to in progress - submission.status.status = SubmissionStatus.IN_PROGRESS + if submission.feedback_counter() == MAX_FEEDBACK_PER_SUBMISSION: + submission.status.status = SubmissionStatus.LIMIT_REACHED submission.status.save() class SubmissionStatus(models.Model): - READY, IN_PROGRESS, LIMIT_REACHED, REVIEWED = range(4) + READY, LIMIT_REACHED = range(2) STATUS = ( (READY, 'READY'), - (IN_PROGRESS, 'IN_PROGRESS'), (LIMIT_REACHED, 'LIMIT_REACHED'), ) @@ -128,18 +134,14 @@ class SubmissionStatus(models.Model): verbose_name_plural = "SubmissionStatus Set" def __str__(self): - return "Status is {} - Count is {}".format(self.status, self.feedback_counter()) - - def feedback_counter(self): - return self.submission.feedback_list.count() - + return "Status is {} - Count is {}".format(self.status, self.submission.feedback_counter()) class Feedback(models.Model): - # Fields score = models.PositiveIntegerField(default=0) text = models.TextField() + final = models.BooleanField(default=False) of_submission = models.ForeignKey( Submission, related_name='feedback_list' @@ -173,7 +175,8 @@ class Feedback(models.Model): @classmethod def tutor_unfinished_feedback(cls, user): - """Gets only the feedback that is assigned and IN_PROGRESS + """Gets only the feedback that is assigned and not final. A tutor + should have only one feedback assigned that is not final Arguments: user {User} -- the tutor who formed the request @@ -182,8 +185,7 @@ class Feedback(models.Model): Feedback -- the feedback or none if no feedback was assigned """ tutor_feedback = cls.objects.filter( - of_tutor=user, - of_submission__status__status=SubmissionStatus.IN_PROGRESS + of_tutor=user, final=False, ) return tutor_feedback[0] if tutor_feedback else None @@ -191,22 +193,16 @@ class Feedback(models.Model): """Gets all feedback that is assigned to the tutor inculuding all status cases. - Only one of these can be IN_PROGRESS and assignments can be discarded - Returns: [list] -- a QuerySet of tasks that have been assigned to this tutor """ - tutor_feedback = cls.objects.filter( - of_tutor=user, - ) - assert 1 == len(tutor_feedback.objects.filter( - of_submission__status__status=SubmissionStatus.IN_PROGRESS)) - return tutor_feedback[0] if tutor_feedback else None + tutor_feedback = cls.objects.filter(of_tutor=user) + assert len(tutor_feedback.objects.filter(final=False)) <= 1 + return tutor_feedback + + def finalize_feedback(self): + self.final = True + self.save() - def unlock_submission(self): - assert self.of_submission.status.status == SubmissionStatus.IN_PROGRESS - if self.of_submission.status.feedback_counter() == MAX_FEEDBACK_PER_SUBMISSION: - self.of_submission.status.status = SubmissionStatus.LIMIT_REACHED - else: - self.of_submission.status.status = SubmissionStatus.READY - self.of_submission.status.save() + def unassign_tutor(self): + self.of_submission.status.status = SubmissionStatus.READY diff --git a/core/templates/base.html b/core/templates/base.html index a06ff8c7..d8de086c 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,3 +1,6 @@ +{% load staticfiles %} + + <!DOCTYPE html> <html lang="en"> <head> diff --git a/core/templates/core/feedback_form.html b/core/templates/core/feedback_form.html index fe50373a..22637b8c 100644 --- a/core/templates/core/feedback_form.html +++ b/core/templates/core/feedback_form.html @@ -16,10 +16,15 @@ </pre> </div> - <form action="" method="post"> + <form action="" method="post" id="form1"> {% csrf_token %} {{ form.as_p }} - <input type="submit" value="Submit"> </form> + <div> + <button type="submit" form="form1" class="btn btn-primary" name="update" value="Submit">Submit</button> + <a href="/feedback/delete/{{ feedback_slug }}/" class="btn btn-primary" name="delete" value="Delete">Delete</a> + </div> + + {% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index 52ce07d0..c0bcb151 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -2,7 +2,7 @@ {% load staticfiles %} -{% block title %} Main Page {% endblock %} +{% block nav_title %} Grady, Sir. Delbert Grady. {% endblock nav_title %} {% block body_block %} <div class="page-header"> diff --git a/core/templates/core/student_startpage.html b/core/templates/core/student_startpage.html new file mode 100644 index 00000000..c829bbee --- /dev/null +++ b/core/templates/core/student_startpage.html @@ -0,0 +1,17 @@ +{% extends 'base.html' %} + +{% load staticfiles %} + +{% block nav_title %} Student Exam View {% endblock nav_title %} + +{% block body_block %} + + <h2>Hello {{ student }}! You can review your exam</h2> + + <ul> + {% for submission in submission_list %} + <li> {{ submission }} </li> + {% endfor %} + </ul> + +{% endblock body_block %} diff --git a/core/templates/core/tutor_startpage.html b/core/templates/core/tutor_startpage.html index 20b002bf..0851dee8 100644 --- a/core/templates/core/tutor_startpage.html +++ b/core/templates/core/tutor_startpage.html @@ -4,8 +4,6 @@ {% block nav_title %} Ready for an exam, commander? {% endblock nav_title %} -{% block title %} Grady -- Login {% endblock %} - {% block body_block %} {% if feedback_list|length == 0 %} <h2>You havn't provided any feedback yet. Sad. Get to work!</h2> @@ -20,6 +18,13 @@ <li> <a href="/feedback/edit/{{ feedback.slug }}/"> {{ feedback }}</a> </li> {% endfor %} </ul> + {% if feedback_not_final|length != 0 %} + <h2>You haven't provided any feddback for this one yet:</h2> + <ul> + <li><a href="/feedback/edit/{{ feedback.slug }}/"> {{ feedback_not_final|first }}</a></li> + </ul> + {% endif %} + {% endif %} <a role="button" class="btn btn-danger btn-xl" href="/feedback/create/">Give me work</a> diff --git a/core/urls.py b/core/urls.py index ee7b84b1..51b043c6 100644 --- a/core/urls.py +++ b/core/urls.py @@ -7,8 +7,10 @@ urlpatterns = [ url(r'^login/$', views.user_login, name='login'), url(r'^logout/$', views.user_logout, name='logout'), url(r'^tutor/$', views.tutor_startpage, name='tutor'), + url(r'^student/$', views.student_startpage, name='student'), url(r'^finished/$', views.finished, name='end'), - url(r'^feedback/create/$', views.create_feedback, name='FeedbackCreate'), url(r'^feedback/edit/(?P<feedback_slug>\w+)/$', views.FeedbackEdit.as_view(), name='FeedbackEdit'), url(r'^feedback/view/(?P<feedback_slug>\w+)/$', views.feedback, name='FeedbackView'), + url(r'^feedback/delete/(?P<feedback_slug>\w+)/$', views.delete_feedback, name='FeedbackDelete'), + url(r'^feedback/create/$', views.create_feedback, name='FeedbackCreate'), ] diff --git a/core/views.py b/core/views.py index 57e11f56..3eeac59d 100644 --- a/core/views.py +++ b/core/views.py @@ -3,10 +3,10 @@ from random import sample from django.contrib.auth import authenticate, login, logout from django.contrib.auth.decorators import login_required, user_passes_test from django.contrib.auth.models import Group, User -from django.http import HttpResponse, HttpResponseRedirect +from django.http import HttpResponse, HttpResponseRedirect, Http404 from django.shortcuts import render from django.utils.decorators import method_decorator -from django.views.generic.edit import CreateView, UpdateView +from django.views.generic.edit import CreateView, UpdateView, DeleteView from core.forms import FeedbackForm from core.models import Feedback, Submission, SubmissionStatus, SubmissionType @@ -14,6 +14,15 @@ from core.models import Feedback, Submission, SubmissionStatus, SubmissionType # Create your views here. +def is_tutor(user): + group = Group.objects.get(name='Tutors') + return group in user.groups.all() + + +def is_student(user): + group = Group.objects.get(name='Students') + return group in user.groups.all() + def index(request): context = { @@ -28,9 +37,9 @@ def delegate_user(user) -> str: if user.groups.filter(name='Tutors').exists(): return '/tutor/' elif user.groups.filter(name='Reviewers').exists(): - return '/reviewers/' + return '/reviewer/' elif user.groups.filter(name='Students').exists(): - return '/students/' + return '/student/' else: return '/' @@ -64,20 +73,25 @@ def user_logout(request): return HttpResponseRedirect('/') -def is_tutor(user): - group = Group.objects.get(name='Tutors') - return group in user.groups.all() - - @user_passes_test(is_tutor, login_url='/') def tutor_startpage(request): context = { 'tutor_name': request.user.username, - 'feedback_list': Feedback.objects.filter(of_tutor=request.user) + 'feedback_list': Feedback.objects.filter(of_tutor=request.user, final=True), + 'feedback_not_final': Feedback.objects.filter(of_tutor=request.user, final=False), } return render(request, 'core/tutor_startpage.html', context) +@user_passes_test(is_student, login_url='/') +def student_startpage(request): + context = { + 'student': request.user, + 'submission_list': Submission.objects.filter(student__user=request.user) + } + return render(request, 'core/student_startpage.html', context) + + @user_passes_test(is_tutor, login_url='/') def feedback(request, feedback_slug): context = {'feedback': Feedback.objects.get(slug=feedback_slug)} @@ -94,6 +108,14 @@ def create_feedback(request): return HttpResponseRedirect('/finished/') return HttpResponseRedirect('/feedback/edit/%s/' % feedback.slug) +def delete_feedback(request, feedback_slug): + """ Hook to ensure object is owned by request.user. """ + instance = Feedback.objects.get(slug=feedback_slug) + if not instance.of_tutor == request.user: + return Http404 + instance.unassign_tutor() + instance.delete() + return HttpResponseRedirect('/tutor/') def finished(request): return HttpResponse("Ich habe fertig.") @@ -112,21 +134,25 @@ class FeedbackEdit(UpdateView): return super(FeedbackEdit, self).dispatch(*args, **kwargs) def get_object(self): - return Feedback.objects.get(slug=self.kwargs['feedback_slug']) + instance = Feedback.objects.get(slug=self.kwargs['feedback_slug']) + if not instance.of_tutor == self.request.user: + raise Http404 + return instance def form_valid(self, form): """ If the form is valid, redirect to the supplied URL. """ - form.instance.unlock_submission() - form.save() + form.instance.finalize_feedback() return HttpResponseRedirect(self.get_success_url()) def get_context_data(self, **kwargs): feedback = self.get_object() context = { 'is_reviewed': not feedback.of_reviewer.all(), + 'feedback_slug': feedback.slug, 'submission': feedback.of_submission, 'submission_type': feedback.of_submission.type, } return super(FeedbackEdit, self).get_context_data(**context) + -- GitLab