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