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