From 36f067710d4afc40e6eda6f4eb63133920d8a57e Mon Sep 17 00:00:00 2001
From: janmax <mail-github@jmx.io>
Date: Thu, 30 Mar 2017 18:57:53 +0200
Subject: [PATCH] added empty submissions

---
 README.rst                                 |   2 +
 core/models.py                             |   3 +-
 core/static/lib/css/codemirror.css         | 341 ---------------------
 core/static/lib/css/custom.css             |  14 +-
 core/static/lib/css/dialog.css             |  32 --
 core/templates/base.html                   |   3 +-
 core/templates/core/feedback_card.html     |   2 +-
 core/templates/core/feedback_form.html     |  11 +-
 core/templates/core/student_startpage.html |   5 +-
 core/views/submission.py                   |   2 +-
 populatedb.py                              |  28 +-
 11 files changed, 53 insertions(+), 390 deletions(-)
 delete mode 100644 core/static/lib/css/codemirror.css
 delete mode 100644 core/static/lib/css/dialog.css

diff --git a/README.rst b/README.rst
index 7a544013..f8f7acc7 100644
--- a/README.rst
+++ b/README.rst
@@ -12,6 +12,8 @@ TODO
 - provide one time passwords for student accounts
 - use postgresql
 - fix seen
+- csv export
+- ilias import
 - versioning for feedback
 - implement better capabilities for the reviewer (optional)
 
diff --git a/core/models.py b/core/models.py
index 778de7c4..41673e02 100644
--- a/core/models.py
+++ b/core/models.py
@@ -59,7 +59,7 @@ class Submission(models.Model):
         SubmissionType,
         related_name='submissions'
     )
-    text = models.TextField()
+    text = models.TextField(blank=True)
     pre_corrections = models.TextField(blank=True)
     final_feedback = models.OneToOneField('Feedback', null=True, blank=True)
     student = models.ForeignKey(Student)
@@ -193,6 +193,7 @@ class Feedback(models.Model):
         self.final = True
         self.of_reviewer = user
         self.of_submission.final_feedback = self
+        self.of_submission.save()
         self.save()
 
     def unfinalize_feedback(self):
diff --git a/core/static/lib/css/codemirror.css b/core/static/lib/css/codemirror.css
deleted file mode 100644
index 2a6a2622..00000000
--- a/core/static/lib/css/codemirror.css
+++ /dev/null
@@ -1,341 +0,0 @@
-/* BASICS */
-
-.CodeMirror {
-  /* Set height, width, borders, and global font properties here */
-  font-family: monospace;
-  height: 300px;
-  color: black;
-}
-
-/* PADDING */
-
-.CodeMirror-lines {
-  padding: 4px 0; /* Vertical padding around content */
-}
-.CodeMirror pre {
-  padding: 0 4px; /* Horizontal padding of content */
-}
-
-.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
-  background-color: white; /* The little square between H and V scrollbars */
-}
-
-/* GUTTER */
-
-.CodeMirror-gutters {
-  border-right: 1px solid #ddd;
-  background-color: #f7f7f7;
-  white-space: nowrap;
-}
-.CodeMirror-linenumbers {}
-.CodeMirror-linenumber {
-  padding: 0 3px 0 5px;
-  min-width: 20px;
-  text-align: right;
-  color: #999;
-  white-space: nowrap;
-}
-
-.CodeMirror-guttermarker { color: black; }
-.CodeMirror-guttermarker-subtle { color: #999; }
-
-/* CURSOR */
-
-.CodeMirror-cursor {
-  border-left: 1px solid black;
-  border-right: none;
-  width: 0;
-}
-/* Shown when moving in bi-directional text */
-.CodeMirror div.CodeMirror-secondarycursor {
-  border-left: 1px solid silver;
-}
-.cm-fat-cursor .CodeMirror-cursor {
-  width: auto;
-  border: 0 !important;
-  background: #7e7;
-}
-.cm-fat-cursor div.CodeMirror-cursors {
-  z-index: 1;
-}
-
-.cm-animate-fat-cursor {
-  width: auto;
-  border: 0;
-  -webkit-animation: blink 1.06s steps(1) infinite;
-  -moz-animation: blink 1.06s steps(1) infinite;
-  animation: blink 1.06s steps(1) infinite;
-  background-color: #7e7;
-}
-@-moz-keyframes blink {
-  0% {}
-  50% { background-color: transparent; }
-  100% {}
-}
-@-webkit-keyframes blink {
-  0% {}
-  50% { background-color: transparent; }
-  100% {}
-}
-@keyframes blink {
-  0% {}
-  50% { background-color: transparent; }
-  100% {}
-}
-
-/* Can style cursor different in overwrite (non-insert) mode */
-.CodeMirror-overwrite .CodeMirror-cursor {}
-
-.cm-tab { display: inline-block; text-decoration: inherit; }
-
-.CodeMirror-rulers {
-  position: absolute;
-  left: 0; right: 0; top: -50px; bottom: -20px;
-  overflow: hidden;
-}
-.CodeMirror-ruler {
-  border-left: 1px solid #ccc;
-  top: 0; bottom: 0;
-  position: absolute;
-}
-
-/* DEFAULT THEME */
-
-.cm-s-default .cm-header {color: blue;}
-.cm-s-default .cm-quote {color: #090;}
-.cm-negative {color: #d44;}
-.cm-positive {color: #292;}
-.cm-header, .cm-strong {font-weight: bold;}
-.cm-em {font-style: italic;}
-.cm-link {text-decoration: underline;}
-.cm-strikethrough {text-decoration: line-through;}
-
-.cm-s-default .cm-keyword {color: #708;}
-.cm-s-default .cm-atom {color: #219;}
-.cm-s-default .cm-number {color: #164;}
-.cm-s-default .cm-def {color: #00f;}
-.cm-s-default .cm-variable,
-.cm-s-default .cm-punctuation,
-.cm-s-default .cm-property,
-.cm-s-default .cm-operator {}
-.cm-s-default .cm-variable-2 {color: #05a;}
-.cm-s-default .cm-variable-3 {color: #085;}
-.cm-s-default .cm-comment {color: #a50;}
-.cm-s-default .cm-string {color: #a11;}
-.cm-s-default .cm-string-2 {color: #f50;}
-.cm-s-default .cm-meta {color: #555;}
-.cm-s-default .cm-qualifier {color: #555;}
-.cm-s-default .cm-builtin {color: #30a;}
-.cm-s-default .cm-bracket {color: #997;}
-.cm-s-default .cm-tag {color: #170;}
-.cm-s-default .cm-attribute {color: #00c;}
-.cm-s-default .cm-hr {color: #999;}
-.cm-s-default .cm-link {color: #00c;}
-
-.cm-s-default .cm-error {color: #f00;}
-.cm-invalidchar {color: #f00;}
-
-.CodeMirror-composing { border-bottom: 2px solid; }
-
-/* Default styles for common addons */
-
-div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
-div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
-.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
-.CodeMirror-activeline-background {background: #e8f2ff;}
-
-/* STOP */
-
-/* The rest of this file contains styles related to the mechanics of
-   the editor. You probably shouldn't touch them. */
-
-.CodeMirror {
-  position: relative;
-  overflow: hidden;
-  background: white;
-}
-
-.CodeMirror-scroll {
-  overflow: scroll !important; /* Things will break if this is overridden */
-  /* 30px is the magic margin used to hide the element's real scrollbars */
-  /* See overflow: hidden in .CodeMirror */
-  margin-bottom: -30px; margin-right: -30px;
-  padding-bottom: 30px;
-  height: 100%;
-  outline: none; /* Prevent dragging from highlighting the element */
-  position: relative;
-}
-.CodeMirror-sizer {
-  position: relative;
-  border-right: 30px solid transparent;
-}
-
-/* The fake, visible scrollbars. Used to force redraw during scrolling
-   before actual scrolling happens, thus preventing shaking and
-   flickering artifacts. */
-.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
-  position: absolute;
-  z-index: 6;
-  display: none;
-}
-.CodeMirror-vscrollbar {
-  right: 0; top: 0;
-  overflow-x: hidden;
-  overflow-y: scroll;
-}
-.CodeMirror-hscrollbar {
-  bottom: 0; left: 0;
-  overflow-y: hidden;
-  overflow-x: scroll;
-}
-.CodeMirror-scrollbar-filler {
-  right: 0; bottom: 0;
-}
-.CodeMirror-gutter-filler {
-  left: 0; bottom: 0;
-}
-
-.CodeMirror-gutters {
-  position: absolute; left: 0; top: 0;
-  min-height: 100%;
-  z-index: 3;
-}
-.CodeMirror-gutter {
-  white-space: normal;
-  height: 100%;
-  display: inline-block;
-  vertical-align: top;
-  margin-bottom: -30px;
-}
-.CodeMirror-gutter-wrapper {
-  position: absolute;
-  z-index: 4;
-  background: none !important;
-  border: none !important;
-}
-.CodeMirror-gutter-background {
-  position: absolute;
-  top: 0; bottom: 0;
-  z-index: 4;
-}
-.CodeMirror-gutter-elt {
-  position: absolute;
-  cursor: default;
-  z-index: 4;
-}
-.CodeMirror-gutter-wrapper {
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  user-select: none;
-}
-
-.CodeMirror-lines {
-  cursor: text;
-  min-height: 1px; /* prevents collapsing before first draw */
-}
-.CodeMirror pre {
-  /* Reset some styles that the rest of the page might have set */
-  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
-  border-width: 0;
-  background: transparent;
-  font-family: inherit;
-  font-size: inherit;
-  margin: 0;
-  white-space: pre;
-  word-wrap: normal;
-  line-height: inherit;
-  color: inherit;
-  z-index: 2;
-  position: relative;
-  overflow: visible;
-  -webkit-tap-highlight-color: transparent;
-  -webkit-font-variant-ligatures: contextual;
-  font-variant-ligatures: contextual;
-}
-.CodeMirror-wrap pre {
-  word-wrap: break-word;
-  white-space: pre-wrap;
-  word-break: normal;
-}
-
-.CodeMirror-linebackground {
-  position: absolute;
-  left: 0; right: 0; top: 0; bottom: 0;
-  z-index: 0;
-}
-
-.CodeMirror-linewidget {
-  position: relative;
-  z-index: 2;
-  overflow: auto;
-}
-
-.CodeMirror-widget {}
-
-.CodeMirror-code {
-  outline: none;
-}
-
-/* Force content-box sizing for the elements where we expect it */
-.CodeMirror-scroll,
-.CodeMirror-sizer,
-.CodeMirror-gutter,
-.CodeMirror-gutters,
-.CodeMirror-linenumber {
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
-}
-
-.CodeMirror-measure {
-  position: absolute;
-  width: 100%;
-  height: 0;
-  overflow: hidden;
-  visibility: hidden;
-}
-
-.CodeMirror-cursor {
-  position: absolute;
-  pointer-events: none;
-}
-.CodeMirror-measure pre { position: static; }
-
-div.CodeMirror-cursors {
-  visibility: hidden;
-  position: relative;
-  z-index: 3;
-}
-div.CodeMirror-dragcursors {
-  visibility: visible;
-}
-
-.CodeMirror-focused div.CodeMirror-cursors {
-  visibility: visible;
-}
-
-.CodeMirror-selected { background: #d9d9d9; }
-.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
-.CodeMirror-crosshair { cursor: crosshair; }
-.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
-.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
-
-.cm-searching {
-  background: #ffa;
-  background: rgba(255, 255, 0, .4);
-}
-
-/* Used to force a border model for a node */
-.cm-force-border { padding-right: .1px; }
-
-@media print {
-  /* Hide the cursor when printing */
-  .CodeMirror div.CodeMirror-cursors {
-    visibility: hidden;
-  }
-}
-
-/* See issue #2901 */
-.cm-tab-wrap-hack:after { content: ''; }
-
-/* Help users use markselection to safely style text background */
-span.CodeMirror-selectedtext { background: none; }
diff --git a/core/static/lib/css/custom.css b/core/static/lib/css/custom.css
index f1ead1ad..5ef326e0 100644
--- a/core/static/lib/css/custom.css
+++ b/core/static/lib/css/custom.css
@@ -1,7 +1,11 @@
 
-.CodeMirror {
-  border: 1px solid #eee;
-  height: auto;
+pre {
+    width: 100%;
+    white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */
+    white-space: -pre-wrap; /* Opera */
+    white-space: -o-pre-wrap; /* Opera */
+    white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation) http://www.w3.org/TR/css3-text/#white-space */
+    word-wrap: break-word; /* IE 5.5+ */
 }
 
 .card-block{
@@ -17,3 +21,7 @@
     height: 500px;
     width: auto;
 }
+
+.nopadding-right {
+   padding-right: 0 !important;
+}
diff --git a/core/static/lib/css/dialog.css b/core/static/lib/css/dialog.css
deleted file mode 100644
index 677c0783..00000000
--- a/core/static/lib/css/dialog.css
+++ /dev/null
@@ -1,32 +0,0 @@
-.CodeMirror-dialog {
-  position: absolute;
-  left: 0; right: 0;
-  background: inherit;
-  z-index: 15;
-  padding: .1em .8em;
-  overflow: hidden;
-  color: inherit;
-}
-
-.CodeMirror-dialog-top {
-  border-bottom: 1px solid #eee;
-  top: 0;
-}
-
-.CodeMirror-dialog-bottom {
-  border-top: 1px solid #eee;
-  bottom: 0;
-}
-
-.CodeMirror-dialog input {
-  border: none;
-  outline: none;
-  background: transparent;
-  width: 20em;
-  color: inherit;
-  font-family: monospace;
-}
-
-.CodeMirror-dialog button {
-  font-size: 70%;
-}
diff --git a/core/templates/base.html b/core/templates/base.html
index ef7f73a3..a8153c3b 100644
--- a/core/templates/base.html
+++ b/core/templates/base.html
@@ -16,7 +16,6 @@
   {# CSS includes #}
   <link rel="stylesheet" href="{% static 'lib/css/bootstrap.min.css' %}">
   <link rel="stylesheet" href="{% static 'lib/css/custom.css' %}">
-  <link rel="stylesheet" href="{% static 'lib/css/dialog.css' %}">
 
   {# Importing stuff for ACE editor #}
   <script src="{% static 'lib/ace/ace.js' %}"></script>
@@ -28,7 +27,7 @@
 </head>
 
 {# Navbar contaning: Brand - Title - Page Title <---> (Username - Logout || Login form) #}
-<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
+<nav class="navbar navbar-toggleable navbar-light bg-faded">
 <a class="navbar-brand" href="{% url 'start' %}">
     <img src="{% static 'res/brand.png' %}" width="30" height="30" class="d-inline-block align-top" alt="">
     Grady
diff --git a/core/templates/core/feedback_card.html b/core/templates/core/feedback_card.html
index 5002989f..882846fd 100644
--- a/core/templates/core/feedback_card.html
+++ b/core/templates/core/feedback_card.html
@@ -2,7 +2,7 @@
   <a data-toggle="collapse" href="#collapse{{unique}}">
     <h5 class="card-header">{{ header }}</h5>
   </a>
-  <div id="collapse{{unique}}" class="collapse hide" role="tabpanel">
+  <div id="collapse{{unique}}" class="collapse {{expanded}}" role="tabpanel">
     <div class="card-block m-2">
       {{ content }}
     </div>
diff --git a/core/templates/core/feedback_form.html b/core/templates/core/feedback_form.html
index 6ed3240f..e11ec442 100644
--- a/core/templates/core/feedback_form.html
+++ b/core/templates/core/feedback_form.html
@@ -8,7 +8,7 @@
 
 {% block body_block %}
 <div class="row">
-  <div class="col my-2">
+  <div class="col my-2 nopadding-right">
 
     <div class="card mb-2">
       <h4 class="card-header">{{feedback.of_submission.type.name}}</h4>
@@ -17,10 +17,10 @@
       </div>
     </div>
 
-    {% include "core/feedback_card.html" with unique="1" header="Description" content=feedback.of_submission.type.task_description expanded="false" %}
-    {% include "core/feedback_card.html" with unique="2" header="Solution" content=feedback.of_submission.type.possible_solution expanded="false" %}
-    {% include "core/feedback_card.html" with unique="3" header="Correction Guideline" content=feedback.of_submission.type.correction_guideline expanded="false" %}
-    {% include "core/feedback_card.html" with unique="4" header="Custom Feedback" content=feedback.of_submission.pre_corrections expanded="false" %}
+    {% include "core/feedback_card.html" with unique="4" header="Custom Feedback" content=feedback.of_submission.pre_corrections expanded="show" %}
+    {% include "core/feedback_card.html" with unique="1" header="Description" content=feedback.of_submission.type.task_description expanded="hide" %}
+    {% include "core/feedback_card.html" with unique="2" header="Solution" content=feedback.of_submission.type.possible_solution expanded="hide" %}
+    {% include "core/feedback_card.html" with unique="3" header="Correction Guideline" content=feedback.of_submission.type.correction_guideline expanded="hide" %}
 
     <div class="my-2">
       <button type="button" id="collapseAllOpen"  class="btn btn-secondary">Open All</button>
@@ -68,7 +68,6 @@
     </form>
       {# This is where all the messages pop up #}
       {% include "core/message_box.html" %}
-      {# This is where all the messages pop up #}
   </div>
 </div>
 
diff --git a/core/templates/core/student_startpage.html b/core/templates/core/student_startpage.html
index cb924e68..14709577 100644
--- a/core/templates/core/student_startpage.html
+++ b/core/templates/core/student_startpage.html
@@ -24,8 +24,9 @@
         <tbody>
           {% for submission in submission_list %}
           <tr class="align-middle">
-            <td class="align-middle">{% if submission.seen %}
-              <span class="badge badge-success">Seen</span>
+            <td class="align-middle">
+              {% if submission.seen %}
+                <span class="badge badge-success">Seen</span>
               {% endif %}</td>
               <td class="align-middle">{{ submission.type }}</td>
               <td class="align-middle">
diff --git a/core/views/submission.py b/core/views/submission.py
index 129e1f85..2320a84f 100644
--- a/core/views/submission.py
+++ b/core/views/submission.py
@@ -16,7 +16,7 @@ class SubmissionView(DetailView):
 
     def get_object(self):
         obj = Submission.objects.get(slug=self.kwargs['slug'])
-        if obj.final_feedback:
+        if obj.final_feedback is not None:
             obj.seen = True
             obj.save()
         return obj
diff --git a/populatedb.py b/populatedb.py
index e81ff5aa..45421e96 100644
--- a/populatedb.py
+++ b/populatedb.py
@@ -12,7 +12,7 @@ django.setup()
 
 from django.contrib.auth.models import Group, User
 
-from core.models import Student, Submission, SubmissionType
+from core.models import Student, Submission, SubmissionType, Feedback
 
 
 def add_submission_type(name,
@@ -52,6 +52,30 @@ def add_submission(type, text, student, pre="Vorgabe"):
     return sub
 
 
+def add_empty_feedback(submission):
+    auto_correct, _ = User.objects.get_or_create(username='auto_correct')
+    feedback = Feedback()
+    feedback.text = "--- You have not submitted any code for this task ---"
+    feedback.final = True
+    feedback.empty = False
+    feedback.of_submission = submission
+    feedback.of_tutor = auto_correct
+    feedback.save()
+    print(f"- Created empty Feedback for Submission {submission}")
+    return feedback
+
+
+def add_empty_submission(type, student):
+    sub = Submission()
+    sub.type = type
+    sub.student = student
+    sub.save()
+    sub.feedback = add_empty_feedback(sub)
+    sub.save()
+    print(f"- Created empty Submission of Type {sub.type}")
+    return sub
+
+
 def add_student(name):
     student_group = Group.objects.get(name='Students')
     student_user = add_user(name, student_group)
@@ -166,6 +190,8 @@ class PopulateDatabase:
             for s, code in submissions.items():
                 if code:
                     add_submission(type_dict[s], code, student)
+                else:
+                    add_empty_submission(type_dict[s], student)
 
 
 # Start execution here!
-- 
GitLab