Start using start dates for exams

This commit is contained in:
Ross
2024-07-08 09:52:01 +01:00
parent 00fa68247d
commit df462efacd
49 changed files with 235 additions and 293 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
{% block navigation %} {% block navigation %}
{{block.super}} {{block.super}}
<br/> <br/>
Exams: {{exam.name}}-> Exams: {{exam}}->
<a href="{% url 'anatomy:exam_overview' pk=exam.pk %}">Overview</a> / <a href="{% url 'anatomy:exam_overview' pk=exam.pk %}">Overview</a> /
{% if exam.exam_mode %} {% if exam.exam_mode %}
<a href="{% url 'anatomy:mark_overview' pk=exam.pk %}">Mark</a> / <a href="{% url 'anatomy:mark_overview' pk=exam.pk %}">Mark</a> /
+1 -1
View File
@@ -2,7 +2,7 @@
{% block content %} {% block content %}
<div class="anatomy"> <div class="anatomy">
<h2>Marking exam: {{ exam.name }}</h2> <h2>Marking exam: {{ exam }}</h2>
You can start marking from a particular question by clicking on it below. You can start marking from a particular question by clicking on it below.
<div> <div>
@@ -45,7 +45,7 @@
</div> </div>
<div> <div>
Exams: {% for exam in question.exams.all %} Exams: {% for exam in question.exams.all %}
<a href="{% url 'anatomy:exam_overview' pk=exam.pk %}">{{ exam.name }}</a> <a href="{% url 'anatomy:exam_overview' pk=exam.pk %}">{{ exam }}</a>
{% endfor %} {% endfor %}
</div> </div>
<div> <div>
@@ -19,7 +19,7 @@
{% if previous > -1 %} {% if previous > -1 %}
<a href="{% url 'anatomy:exam_question_detail' exam.id previous %}">Previous question</a> <a href="{% url 'anatomy:exam_question_detail' exam.id previous %}">Previous question</a>
{% endif %} {% endif %}
Viewing question as part of exam: <a href="{% url 'anatomy:exam_overview' exam.id %}">{{exam.name}}</a> [{{pos}}/{{exam_length}}] Viewing question as part of exam: <a href="{% url 'anatomy:exam_overview' exam.id %}">{{exam}}</a> [{{pos}}/{{exam_length}}]
{% if next %} {% if next %}
<a href="{% url 'anatomy:exam_question_detail' exam.id next %}">Next question</a> <a href="{% url 'anatomy:exam_question_detail' exam.id next %}">Next question</a>
{% endif %} {% endif %}
+3 -3
View File
@@ -303,7 +303,7 @@ def test_exams(db, client):
.find("li", attrs={"data-exam-id": exam.pk}) .find("li", attrs={"data-exam-id": exam.pk})
) )
assert search_exam assert search_exam
assert exam.name in str(search_exam) assert str(exam) in str(search_exam)
assert len(search_exam.find("button", {"class": "start-button"})) > 0 assert len(search_exam.find("button", {"class": "start-button"})) > 0
# assert "Active" in assigned_exams # check it is active # assert "Active" in assigned_exams # check it is active
@@ -319,8 +319,8 @@ def test_exams(db, client):
.find_all("li", attrs={"data-exam-id": exam.pk}) .find_all("li", attrs={"data-exam-id": exam.pk})
) )
assert results_exam assert results_exam
assert exam.name in str(results_exam) assert str(exam) in str(results_exam)
assert exam.name + " test" not in str(results_exam) assert str(exam) + " test" not in str(results_exam)
assert "Results Published" not in str( assert "Results Published" not in str(
results_exam results_exam
) # It should not be published yet ) # It should not be published yet
+5
View File
@@ -47,6 +47,7 @@ from generic.models import (
CidUserExam, CidUserExam,
CidUserGroup, CidUserGroup,
ExamOrCollectionGenericBase, ExamOrCollectionGenericBase,
ExamUserStatus,
Examination, Examination,
# Condition, # Condition,
ExamBase, ExamBase,
@@ -775,6 +776,8 @@ class CaseCollection(ExamOrCollectionGenericBase):
help_text="If true allows users self complete and review cases in a self directed way.", help_text="If true allows users self complete and review cases in a self directed way.",
) )
exam_user_status = GenericRelation(ExamUserStatus)
feedback_once_collection_complete = models.BooleanField(default=True, help_text="If true feedback is only given once the collection is complete. If false feedback is given after each case.") feedback_once_collection_complete = models.BooleanField(default=True, help_text="If true feedback is only given once the collection is complete. If false feedback is given after each case.")
class COLLECTION_TYPE_CHOICES(models.TextChoices): class COLLECTION_TYPE_CHOICES(models.TextChoices):
@@ -996,6 +999,8 @@ class CaseDetail(models.Model):
question_schema = models.JSONField(null=True, blank=True) question_schema = models.JSONField(null=True, blank=True)
question_answers = models.JSONField(null=True, blank=True) question_answers = models.JSONField(null=True, blank=True)
# TODO add feedback for questions
#question_feedback = models.JSONField(null=True, blank=True)
sort_order = models.IntegerField(default=1000) sort_order = models.IntegerField(default=1000)
@@ -177,7 +177,7 @@
{% endif %} {% endif %}
</div> </div>
<details><summary>View questions</summary> <details><summary class="opacity-50">View questions</summary>
{{form.json.errors}} {{form.json.errors}}
<div class="form-contents"> <div class="form-contents">
<fieldset {% if question_completed %}disabled="disabled"{% endif %}> <fieldset {% if question_completed %}disabled="disabled"{% endif %}>
@@ -1,7 +1,7 @@
{% extends 'atlas/base.html' %} {% extends 'atlas/base.html' %}
{% block content %} {% block content %}
<h2>Collection: {{exam.name}}</h2> <h2>Collection: {{exam}}</h2>
{% comment %} <ul> {% comment %} <ul>
{% for case in collection.cases.all %} {% for case in collection.cases.all %}
+1 -1
View File
@@ -9,6 +9,6 @@
<h3>My cases / collections</h3> <h3>My cases / collections</h3>
View my <a href='{% url "atlas:case_view" %}?author={{request.user.id}}'>cases</a>.<br/> View my <a href='{% url "atlas:case_view" %}?author={{request.user.id}}'>cases</a>.<br/>
<a href="{% url 'atlas:user_uploads' %}"><button><i class="bi bi-cloud-arrow-up"></i> Uploads awaiting import</button></a> <a href="{% url 'atlas:user_uploads' %}"><i class="bi bi-cloud-arrow-up"></i> Uploads awaiting import</a>
{% endblock %} {% endblock %}
+10
View File
@@ -1914,6 +1914,16 @@ def collection_take_overview(
cid_user_exam.completed = True cid_user_exam.completed = True
cid_user_exam.save() cid_user_exam.save()
if cid is not None:
c = CidUser.objects.get(cid=cid)
collection.exam_user_status.create(
cid_user=c, user_user=None, status="submitted", extra="manual submission"
)
else:
collection.exam_user_status.create(
cid_user=None, user_user=request.user, status="submitted", extra="manual submission"
)
return HttpResponse("True") return HttpResponse("True")
else: else:
raise Http404() raise Http404()
+8 -3
View File
@@ -869,6 +869,14 @@ class ExamBase(ExamOrCollectionGenericBase):
class Meta: class Meta:
abstract = True abstract = True
def __str__(self):
print("TESTING")
if self.start_date and self.start_date is not None:
print(f"Start date: {self.start_date:%d %B %Y}")
return f"{self.name} ({self.start_date:%d %B %Y})"
else:
return self.name
def save(self, *args, recreate_json=True, **kwargs): def save(self, *args, recreate_json=True, **kwargs):
self.recreate_json = recreate_json self.recreate_json = recreate_json
@@ -903,9 +911,6 @@ class ExamBase(ExamOrCollectionGenericBase):
""" """
return text return text
def __str__(self):
return self.name
def get_absolute_url(self): def get_absolute_url(self):
return reverse("{}:exam_overview".format(self.app_name), kwargs={"pk": self.pk}) return reverse("{}:exam_overview".format(self.app_name), kwargs={"pk": self.pk})
+1 -1
View File
@@ -20,7 +20,7 @@
{% else %} {% else %}
Packet: Packet:
{% endif %} {% endif %}
{{ exam.name }} </a></h1> {{ exam }} </a></h1>
<span class="authors">Authors: {{exam.get_authors}}</span> <span class="authors">Authors: {{exam.get_authors}}</span>
{% if exam.exam_mode %} {% if exam.exam_mode %}
{% if app_name in "rapids longs anatomy" %} {% if app_name in "rapids longs anatomy" %}
@@ -1,5 +1,5 @@
{% include "generic/exam_link_headers.html" %} {% include "generic/exam_link_headers.html" %}
<h1>Exam: {{ exam.name }}</h1> <h1>Exam: {{ exam }}</h1>
{% include 'exam_notes.html' %} {% include 'exam_notes.html' %}
@@ -2,7 +2,7 @@
{% block content %} {% block content %}
<div class=""> <div class="">
<h2>{{ exam.name }}</h2> <h2>{{ exam }}</h2>
{% if cached_scores %} {% if cached_scores %}
User answer scores are cached, if you update or change an answer you will need to <a href="{% url exam.app_name|add:':exam_scores_refresh' exam.pk %}">refresh the scores</a>. User answer scores are cached, if you update or change an answer you will need to <a href="{% url exam.app_name|add:':exam_scores_refresh' exam.pk %}">refresh the scores</a>.
{% endif %} {% endif %}
+3 -7
View File
@@ -556,7 +556,7 @@ class ExamViews(View, LoginRequiredMixin):
data = { data = {
"status": "success", "status": "success",
"archive": exam.archive, "archive": exam.archive,
"name": exam.name, "name": exam,
"id": exam.id, "id": exam.id,
} }
return JsonResponse(data, status=200) return JsonResponse(data, status=200)
@@ -580,7 +580,7 @@ class ExamViews(View, LoginRequiredMixin):
data = { data = {
"status": "success", "status": "success",
"publish_results": exam.publish_results, "publish_results": exam.publish_results,
"name": exam.name, "name": exam,
"id": exam.id, "id": exam.id,
} }
return JsonResponse(data, status=200) return JsonResponse(data, status=200)
@@ -602,7 +602,7 @@ class ExamViews(View, LoginRequiredMixin):
data = { data = {
"status": "success", "status": "success",
"active": exam.active, "active": exam.active,
"name": exam.name, "name": exam,
"id": exam.id, "id": exam.id,
} }
return JsonResponse(data, status=200) return JsonResponse(data, status=200)
@@ -1483,13 +1483,9 @@ class ExamViews(View, LoginRequiredMixin):
exam: ExamBase exam: ExamBase
for exam in exams: for exam in exams:
if exam.active or self.check_user_access(request.user, exam.pk): if exam.active or self.check_user_access(request.user, exam.pk):
print(
f"{exam.app_name=}, {exam.name=}, {cid=}, {passcode=}, {request.user=}"
)
if exam.exam_mode and not exam.check_cid_user( if exam.exam_mode and not exam.check_cid_user(
cid, passcode, user=request.user, user_id=request.user.pk cid, passcode, user=request.user, user_id=request.user.pk
): ):
print(exam.name, "fail")
continue continue
if exam.json_creation_time: if exam.json_creation_time:
-74
View File
@@ -19,77 +19,3 @@
{% endblock table_answers %} {% endblock table_answers %}
{% comment %} {% extends 'longs/exams.html' %}
{% block content %}
<div class="longs">
<h2>{{ exam.name }}</h2>
{% if unmarked %}
<div class="alert alert-warning" role="alert">
The following questions need marking
{% for exam_index in unmarked %}
<a href="{% url 'longs:mark' exam.pk exam_index %}">{{ exam_index|add:1 }}</a>
{% endfor %}
</div>
{% endif %}
</div>
<div id="stats-block">
<h3>Stats</h3>
Candidates: {{cids|length}}<br />
Available marks: {{max_score}}<br />
Mean: {{mean}}, Median {{median}}, Mode {{mode}}
<div id="stats-plot">{{plot|safe}}</div>
</div>
<div class="col-sm-4">
<table class="table table-dark table-striped table-hover table-sm">
<tr>
<th>Candidate ID</th>
<th>Score</th>
<th>Normalised score</th>
</tr>
{% for user, value in user_answers_marks.items %}
<tr>
<td><a href="{% url 'cid_scores_admin' user %}">{{user}}</a></td>
<td>{{user_scores|get_item:user}}</td>
<td>{{user_scores_normalised|get_item:user}}</td>
</tr>
{% endfor %}
</table>
</div>
<div class="col">
<h3>Results as a table</h3>
<table class="longs table table-dark table-striped table-hover table-sm">
<thead class="thead-dark">
<tr>
<th>Candidate</th>
{% for cid in cids %}
<th><a href="{% url 'longs:exam_scores_cid_user' exam.pk cid 'None' %}">{{cid}}</a></th>
{% endfor %}
</tr>
</thead>
{% for question in questions %}
<tr>
<td><a href="{% url 'longs:mark' exam_id=exam.pk sk=forloop.counter0 %}">Question
{{forloop.counter}}</a></td>
{% for ans, score in by_question|get_item:question %}
<td class="user-answer-score-{{score}}" title="answer score: {{score}}">{{score}}</td>
{% endfor %}
</tr>
{% endfor %}
<tr>
<td>Score:</td>
{% for score in user_scores_list %}
<td>{{score}}</td>
{% endfor %}
<tr>
</table>
</div>
{% endblock %} {% endcomment %}
+1 -1
View File
@@ -3,7 +3,7 @@
{% block navigation %} {% block navigation %}
{{block.super}} {{block.super}}
<br/> <br/>
Exams: {{exam.name}}-> Exams: {{exam}}->
<a href="{% url 'longs:exam_overview' pk=exam.pk %}">Overview</a> / <a href="{% url 'longs:exam_overview' pk=exam.pk %}">Overview</a> /
<a href="{% url 'longs:mark_overview' pk=exam.pk %}">Mark</a> / <a href="{% url 'longs:mark_overview' pk=exam.pk %}">Mark</a> /
<a href="{% url 'longs:exam_scores_all' pk=exam.pk %}">Scores</a> / <a href="{% url 'longs:exam_scores_all' pk=exam.pk %}">Scores</a> /
@@ -70,7 +70,7 @@
</p> </p>
<div> <div>
Exam(s): {% for exam in question.exams.all %} Exam(s): {% for exam in question.exams.all %}
<a href="{% url 'longs:exam_overview' pk=exam.pk %}">{{ exam.name }}</a>, <a href="{% url 'longs:exam_overview' pk=exam.pk %}">{{ exam }}</a>,
{% endfor %} {% endfor %}
</div> </div>
<div> <div>
+1 -1
View File
@@ -2,7 +2,7 @@
{% block content %} {% block content %}
<div class="longs"> <div class="longs">
<h2>Marking exam: {{ exam.name }}</h2> <h2>Marking exam: {{ exam }}</h2>
You can start marking from a particular question by clicking on it below. You can start marking from a particular question by clicking on it below.
<div> <div>
+1 -1
View File
@@ -18,7 +18,7 @@
{% if previous > -1 %} {% if previous > -1 %}
<a href="{% url 'longs:exam_question_detail' exam.id previous %}">Previous question</a> <a href="{% url 'longs:exam_question_detail' exam.id previous %}">Previous question</a>
{% endif %} {% endif %}
Viewing question as part of exam: <a href="{% url 'longs:exam_overview' exam.id %}">{{exam.name}}</a> [{{pos}}/{{exam_length}}] Viewing question as part of exam: <a href="{% url 'longs:exam_overview' exam.id %}">{{exam}}</a> [{{pos}}/{{exam_length}}]
{% if next %} {% if next %}
<a href="{% url 'longs:exam_question_detail' exam.id next %}">Next question</a> <a href="{% url 'longs:exam_question_detail' exam.id next %}">Next question</a>
{% endif %} {% endif %}
+3 -3
View File
@@ -445,7 +445,7 @@ def test_exams(db, client):
.find("li", attrs={"data-exam-id": exam.pk}) .find("li", attrs={"data-exam-id": exam.pk})
) )
assert search_exam assert search_exam
assert exam.name in str(search_exam) assert str(exam) in str(search_exam)
assert len(search_exam.find("button", {"class": "start-button"})) > 0 assert len(search_exam.find("button", {"class": "start-button"})) > 0
# assert "Active" in assigned_exams # check it is active # assert "Active" in assigned_exams # check it is active
@@ -461,8 +461,8 @@ def test_exams(db, client):
.find_all("li", attrs={"data-exam-id": exam.pk}) .find_all("li", attrs={"data-exam-id": exam.pk})
) )
assert results_exam assert results_exam
assert exam.name in str(results_exam) assert str(exam) in str(results_exam)
assert exam.name + " test" not in str(results_exam) assert str(exam) + " test" not in str(results_exam)
assert "Results Published" not in str( assert "Results Published" not in str(
results_exam results_exam
) # It should not be published yet ) # It should not be published yet
@@ -8,7 +8,7 @@
{% for exam in exams %} {% for exam in exams %}
{% if exam.active %} {% if exam.active %}
<li> <li>
<a href="{% url 'physics:exam_start' pk=exam.pk %}">{{exam.name}}</a> <a href="{% url 'physics:exam_start' pk=exam.pk %}">{{exam}}</a>
</li> </li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
+1 -1
View File
@@ -2,7 +2,7 @@
{% block content %} {% block content %}
<h2>Start exam: {{exam.name}}</h2> <h2>Start exam: {{exam}}</h2>
{% if exam.time_limit %} {% if exam.time_limit %}
This exam has a time limit of {{ exam.get_time_limit }}. The time will start when you click the Start Exam button below.<br/> This exam has a time limit of {{ exam.get_time_limit }}. The time will start when you click the Start Exam button below.<br/>
+1 -1
View File
@@ -10,7 +10,7 @@
</span> </span>
{% include "exam_clock.html" %} {% include "exam_clock.html" %}
<div class="no-select"> <div class="no-select">
<h2>{{exam.name}}: Question [<span id="question-number">{{pos|add:1}}</span>/<span id="exam-length">{{exam_length}}</span>]</h2> <h2>{{exam}}: Question [<span id="question-number">{{pos|add:1}}</span>/<span id="exam-length">{{exam_length}}</span>]</h2>
{% if exam.publish_results %} {% if exam.publish_results %}
<div class="alert alert-primary review-mode-alert" role="alert"> <div class="alert alert-primary review-mode-alert" role="alert">
Exam is in review mode. Add question feedback <a href="#" onclick="return window.create_popup_window('{% url 'feedback_create' question_type='physics' pk=question.pk %}')">here</a>. Exam is in review mode. Add question feedback <a href="#" onclick="return window.create_popup_window('{% url 'feedback_create' question_type='physics' pk=question.pk %}')">here</a>.
+1 -1
View File
@@ -3,7 +3,7 @@
{% block content %} {% block content %}
<div class="physics"> <div class="physics">
<h1>Exam: {{ exam.name }}</h1> <h1>Exam: {{ exam }}</h1>
<div class="alert alert-info" role="alert"> <div class="alert alert-info" role="alert">
<details> <details>
@@ -10,7 +10,7 @@
</span> </span>
{% include "exam_clock.html" %} {% include "exam_clock.html" %}
<h2>Exam: {{exam.name}}</h2> <h2>Exam: {{exam}}</h2>
{% if exam.publish_results %} {% if exam.publish_results %}
<div class="alert alert-primary review-mode-alert" role="alert"> <div class="alert alert-primary review-mode-alert" role="alert">
+1 -1
View File
@@ -3,7 +3,7 @@
{% block navigation %} {% block navigation %}
{{block.super}} {{block.super}}
<br/> <br/>
Exams: {{exam.name}}-> <a href="{% url 'physics:exam_overview' pk=exam.pk %}">Overview</a> / Exams: {{exam}}-> <a href="{% url 'physics:exam_overview' pk=exam.pk %}">Overview</a> /
<a href="{% url 'physics:exam_scores_all' pk=exam.pk %}">Scores</a> / <a href="{% url 'physics:exam_scores_all' pk=exam.pk %}">Scores</a> /
<a href="{% url 'physics:exam_cids' exam_id=exam.pk %}">Candidates</a> / <a href="{% url 'physics:exam_cids' exam_id=exam.pk %}">Candidates</a> /
<a href="{% url 'physics:exam_stats' exam_id=exam.pk %}">Stats</a> / <a href="{% url 'physics:exam_stats' exam_id=exam.pk %}">Stats</a> /
@@ -21,7 +21,7 @@
{% endautoescape %} {% endautoescape %}
<div> <div>
Examinations: {% for exam in question.exams.all %} Examinations: {% for exam in question.exams.all %}
<a href="{% url 'physics:exam_overview' pk=exam.pk %}">{{ exam.name }}</a> <a href="{% url 'physics:exam_overview' pk=exam.pk %}">{{ exam }}</a>
{% endfor %} {% endfor %}
</div> </div>
<div> <div>
+3 -3
View File
@@ -342,7 +342,7 @@ class ExamTester:
.find("li", attrs={"data-exam-id": self.exam.pk}) .find("li", attrs={"data-exam-id": self.exam.pk})
) )
assert search_exam assert search_exam
assert self.exam.name in str(search_exam) assert str(self.exam) in str(search_exam)
assert len(search_exam.find("button", {"class": "start-button"})) > 0 assert len(search_exam.find("button", {"class": "start-button"})) > 0
# assert "Active" in assigned_exams # check it is active # assert "Active" in assigned_exams # check it is active
@@ -358,8 +358,8 @@ class ExamTester:
.find_all("li", attrs={"data-exam-id": self.exam.pk}) .find_all("li", attrs={"data-exam-id": self.exam.pk})
) )
assert results_exam assert results_exam
assert self.exam.name in str(results_exam) assert str(self.exam) in str(results_exam)
assert self.exam.name + " test" not in str(results_exam) assert str(self.exam) + " test" not in str(results_exam)
assert "Results Published" not in str( assert "Results Published" not in str(
results_exam results_exam
) # It should not be published yet ) # It should not be published yet
+1 -1
View File
@@ -3,7 +3,7 @@
{% block navigation %} {% block navigation %}
{{block.super}} {{block.super}}
<br/> <br/>
Exams: {{exam.name}}-> Exams: {{exam}}->
<a href="{% url 'rapids:exam_overview' pk=exam.pk %}">Overview</a> / <a href="{% url 'rapids:exam_overview' pk=exam.pk %}">Overview</a> /
{% if exam.exam_mode %} {% if exam.exam_mode %}
<a href="{% url 'rapids:mark_overview' pk=exam.pk %}">Mark</a> / <a href="{% url 'rapids:mark_overview' pk=exam.pk %}">Mark</a> /
+19 -19
View File
@@ -1,20 +1,20 @@
{% extends 'rapids/exams.html' %} {% extends 'rapids/exams.html' %}
{% block content %} {% block content %}
<div class="rapids"> <div class="rapids">
<h2>Marking exam: {{ exam.name }}</h2> <h2>Marking exam: {{ exam }}</h2>
You can start marking from a particular question by clicking on it below. You can start marking from a particular question by clicking on it below.
<div> <div>
<button class="show-all-button">Show all</button><button class="show-unmarked-button">Show unmarked</button> <button class="show-all-button">Show all</button><button class="show-unmarked-button">Show unmarked</button>
</div> </div>
<div id="stark-marking-button"><a href="{% url 'rapids:mark' exam_pk=exam.pk sk=0 %}"><button>Click here to start marking</button></a></div> <div id="stark-marking-button"><a href="{% url 'rapids:mark' exam_pk=exam.pk sk=0 %}"><button>Click here to start marking</button></a></div>
<ul id="question-mark-list"> <ul id="question-mark-list">
{% for question, unmarked_count, unmarked_count2 in question_unmarked_map %} {% for question, unmarked_count, unmarked_count2 in question_unmarked_map %}
<li data-markcount={{unmarked_count}} {% if unmarked_count %}class="unmarked" {% endif %}><a href="{% url 'rapids:mark' exam_pk=exam.pk sk=forloop.counter0 %}">Question {{forloop.counter }}: <li data-markcount={{unmarked_count}} {% if unmarked_count %}class="unmarked" {% endif %}><a href="{% url 'rapids:mark' exam_pk=exam.pk sk=forloop.counter0 %}">Question {{forloop.counter }}:
{{ question }}</a><br />Unmarked answers: {{unmarked_count}}</li> {{ question }}</a><br />Unmarked answers: {{unmarked_count}}</li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
{% endblock %} {% endblock %}
@@ -30,7 +30,7 @@
</div> </div>
<div> <div>
Exam(s): {% for exam in question.exams.all %} Exam(s): {% for exam in question.exams.all %}
<a href="{% url 'rapids:exam_overview' pk=exam.pk %}">{{ exam.name }}</a>, <a href="{% url 'rapids:exam_overview' pk=exam.pk %}">{{ exam }}</a>,
{% endfor %} {% endfor %}
{% comment %} <button id="add-to-exam" data-exam_json_edit_url="{% url 'generic:generic_exam_json_edit' %}" {% comment %} <button id="add-to-exam" data-exam_json_edit_url="{% url 'generic:generic_exam_json_edit' %}"
@@ -1,25 +1,25 @@
<div class="floating-header"> <div class="floating-header">
<a href="{% url 'rapids:rapid_update' pk=question.pk %}" title="Edit the Rapid">Edit</a> <a href="{% url 'rapids:rapid_update' pk=question.pk %}" title="Edit the Rapid">Edit</a>
<a href="{% url 'rapids:rapid_clone' pk=question.pk %}" title="Clone the Rapid (duplicate everything but the images)">Clone</a> <a href="{% url 'rapids:rapid_clone' pk=question.pk %}" title="Clone the Rapid (duplicate everything but the images)">Clone</a>
<a href="{% url 'rapids:question_delete' pk=question.pk %}" title="Delete the Rapid">Delete</a> <a href="{% url 'rapids:question_delete' pk=question.pk %}" title="Delete the Rapid">Delete</a>
<a href="{% url 'rapids:question_answer_update' pk=question.pk %}" title="Update the question answers">Edit Answers</a> <a href="{% url 'rapids:question_answer_update' pk=question.pk %}" title="Update the question answers">Edit Answers</a>
<a href="#" onclick="return window.create_popup_window('{% url 'feedback_create' question_type='rapid' pk=question.pk %}')"> Add Note</a> <a href="#" onclick="return window.create_popup_window('{% url 'feedback_create' question_type='rapid' pk=question.pk %}')"> Add Note</a>
{% if request.user.is_superuser %} {% if request.user.is_superuser %}
<a href="{% url 'admin:rapids_rapid_change' question.id %}" title="Edit the Rapid using the admin interface">Admin Edit</a> <a href="{% url 'admin:rapids_rapid_change' question.id %}" title="Edit the Rapid using the admin interface">Admin Edit</a>
<a href="{% url 'rapids:question_user_answers' question.id %}" title="View user answers associated with this question">User answers</a> <a href="{% url 'rapids:question_user_answers' question.id %}" title="View user answers associated with this question">User answers</a>
{% endif %} {% endif %}
{% if exam %} {% if exam %}
<div> <div>
{% if previous > -1 %} {% if previous > -1 %}
<a href="{% url 'rapids:exam_question_detail' exam.id previous %}">Previous question</a> <a href="{% url 'rapids:exam_question_detail' exam.id previous %}">Previous question</a>
{% endif %} {% endif %}
Viewing question as part of exam: <a href="{% url 'rapids:exam_overview' exam.id %}">{{exam.name}}</a> [{{pos}}/{{exam_length}}] Viewing question as part of exam: <a href="{% url 'rapids:exam_overview' exam.id %}">{{exam}}</a> [{{pos}}/{{exam_length}}]
{% if next %} {% if next %}
<a href="{% url 'rapids:exam_question_detail' exam.id next %}">Next question</a> <a href="{% url 'rapids:exam_question_detail' exam.id next %}">Next question</a>
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}
</div> </div>
+3 -3
View File
@@ -340,7 +340,7 @@ def test_exams(db, client):
.find("li", attrs={"data-exam-id": exam.pk}) .find("li", attrs={"data-exam-id": exam.pk})
) )
assert search_exam assert search_exam
assert exam.name in str(search_exam) assert str(exam) in str(search_exam)
assert len(search_exam.find("button", {"class": "start-button"})) > 0 assert len(search_exam.find("button", {"class": "start-button"})) > 0
# assert "Active" in assigned_exams # check it is active # assert "Active" in assigned_exams # check it is active
@@ -356,8 +356,8 @@ def test_exams(db, client):
.find_all("li", attrs={"data-exam-id": exam.pk}) .find_all("li", attrs={"data-exam-id": exam.pk})
) )
assert results_exam assert results_exam
assert exam.name in str(results_exam) assert str(exam) in str(results_exam)
assert exam.name + " test" not in str(results_exam) assert str(exam) + " test" not in str(results_exam)
assert "Results Published" not in str( assert "Results Published" not in str(
results_exam results_exam
) # It should not be published yet ) # It should not be published yet
+13 -13
View File
@@ -1,19 +1,19 @@
{% extends 'sbas/base.html' %} {% extends 'sbas/base.html' %}
{% block content %} {% block content %}
<h1>Examinations</h1> <h1>Examinations</h1>
<div class="sbas"> <div class="sbas">
Active exams:<br/> Active exams:<br/>
<ul> <ul>
{% for exam in exams %} {% for exam in exams %}
{% if exam.active %} {% if exam.active %}
<li> <li>
<a href="{% url 'sbas:exam_start' pk=exam.pk %}">{{exam.name}}</a> <a href="{% url 'sbas:exam_start' pk=exam.pk %}">{{exam}}</a>
</li> </li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
{% endblock %} {% endblock %}
+36 -36
View File
@@ -2,54 +2,54 @@
{% block content %} {% block content %}
<h2>Start exam: {{exam.name}}</h2> <h2>Start exam: {{exam}}</h2>
{% if exam.time_limit %} {% if exam.time_limit %}
This exam has a time limit of {{ exam.get_time_limit }}. The time will start when you click the Start Exam button below.<br/> This exam has a time limit of {{ exam.get_time_limit }}. The time will start when you click the Start Exam button below.<br/>
{% endif %} {% endif %}
{% if request.user.is_authenticated and valid_user %} {% if request.user.is_authenticated and valid_user %}
<a href="{% url 'sbas:exam_take_user' pk=exam.pk sk=0 %}">Start Exam</a> <a href="{% url 'sbas:exam_take_user' pk=exam.pk sk=0 %}">Start Exam</a>
{% else %} {% else %}
Enter your CID and passcode in the below boxes.<br /> Enter your CID and passcode in the below boxes.<br />
<p><input id="cid-box" type="text" value="Candidate ID"></p> <p><input id="cid-box" type="text" value="Candidate ID"></p>
<p><input id="passcode-box" type="text" value="Passcode"></p> <p><input id="passcode-box" type="text" value="Passcode"></p>
<button>Start exam</button> <button>Start exam</button>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function () { $(document).ready(function () {
window.location.search.substr(1).split("&").forEach((item) => window.location.search.substr(1).split("&").forEach((item) =>
{ {
s = item.split("="); s = item.split("=");
if (s[0] == "cid") { if (s[0] == "cid") {
$("#cid-box").val(s[1]); $("#cid-box").val(s[1]);
} }
if (s[0] == "passcode") { if (s[0] == "passcode") {
$("#passcode-box").val(s[1]); $("#passcode-box").val(s[1]);
}
});
$("#cid-box, #passcode-box").keypress(function(e) {
// Enter pressed?
console.log(e)
if(e.which == 10 || e.which == 13) {
$("button").click();
} }
}); });
$("#cid-box, #passcode-box").keypress(function(e) { $("button").click(() => {
// Enter pressed? let cid = $("#cid-box").val();
console.log(e) let passcode = $("#passcode-box").val();
if(e.which == 10 || e.which == 13) {
$("button").click();
}
});
$("button").click(() => { if (Number.isInteger(parseInt(cid))) {
let cid = $("#cid-box").val(); window.location.replace("{% url 'sbas:exam_take' pk=exam.pk sk=0 cid='0000000' passcode='ZZZZZZ' %}".replace("0000000", cid).replace("ZZZZZZ", passcode));
let passcode = $("#passcode-box").val(); } else {
alert("Please enter a valid Candidate ID (CID).")
if (Number.isInteger(parseInt(cid))) { }
window.location.replace("{% url 'sbas:exam_take' pk=exam.pk sk=0 cid='0000000' passcode='ZZZZZZ' %}".replace("0000000", cid).replace("ZZZZZZ", passcode)); });
} else {
alert("Please enter a valid Candidate ID (CID).")
}
}); });
}); </script>
</script>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
+11 -11
View File
@@ -10,7 +10,7 @@
</span> </span>
{% include "exam_clock.html" %} {% include "exam_clock.html" %}
<div class="no-select"> <div class="no-select">
<h2>{{exam.name}}: Question [<span id="question-number">{{pos|add:1}}</span>/<span id="exam-length">{{exam_length}}</span>]</h2> <h2>{{exam}}: Question [<span id="question-number">{{pos|add:1}}</span>/<span id="exam-length">{{exam_length}}</span>]</h2>
{% if exam.publish_results %} {% if exam.publish_results %}
<div class="alert alert-primary review-mode-alert" role="alert"> <div class="alert alert-primary review-mode-alert" role="alert">
Exam is in review mode. Add question feedback <a href="#" onclick="return window.create_popup_window('{% url 'feedback_create' question_type='sbas' pk=question.pk %}')">here</a>. Exam is in review mode. Add question feedback <a href="#" onclick="return window.create_popup_window('{% url 'feedback_create' question_type='sbas' pk=question.pk %}')">here</a>.
@@ -64,16 +64,16 @@
</div> </div>
<details><summary>Help</summary> <details><summary>Help</summary>
<p>Each question contains a list of 5 different statements. One of these is the single BEST answer.</p> <p>Each question contains a list of 5 different statements. One of these is the single BEST answer.</p>
<p>Click on the correct statement to select it. Once selected it will be highlighted. </p> <p>Click on the correct statement to select it. Once selected it will be highlighted. </p>
<p>Your answers are saved when navigating between questions (or if the save button is clicked on the final question). An overview of all the questions can be seen by clicking on the overview button (or by clicking <a target="_blank" href=" <p>Your answers are saved when navigating between questions (or if the save button is clicked on the final question). An overview of all the questions can be seen by clicking on the overview button (or by clicking <a target="_blank" href="
{% if cid %} {% if cid %}
{% url 'sbas:exam_scores_cid_user' pk=exam.pk cid=cid passcode=passcode %} {% url 'sbas:exam_scores_cid_user' pk=exam.pk cid=cid passcode=passcode %}
{% else %} {% else %}
{% url 'sbas:exam_scores_user' pk=exam.pk %} {% url 'sbas:exam_scores_user' pk=exam.pk %}
{% endif %} {% endif %}
" "
>here</a>).</p> >here</a>).</p>
</details> </details>
{% endblock %} {% endblock %}
+10 -10
View File
@@ -2,19 +2,19 @@
{% block content %} {% block content %}
<span id="user-id"> <span id="user-id">
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
User: {{request.user}} User: {{request.user}}
{% else %} {% else %}
CID: {{cid}} CID: {{cid}}
{% endif %} {% endif %}
</span> </span>
{% include "exam_clock.html" %} {% include "exam_clock.html" %}
<h2>Exam: {{exam.name}}</h2> <h2>Exam: {{exam}}</h2>
{% if exam.publish_results %} {% if exam.publish_results %}
<div class="alert alert-primary review-mode-alert" role="alert"> <div class="alert alert-primary review-mode-alert" role="alert">
Exam is in review mode. Score are available Exam is in review mode. Score are available
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
<a href="{% url 'sbas:exam_scores_user' pk=exam.id %}">here</a> <a href="{% url 'sbas:exam_scores_user' pk=exam.id %}">here</a>
@@ -29,7 +29,7 @@
You have unanswered questions. You have unanswered questions.
</div> </div>
{% endif %} {% endif %}
<div class="overview-text">{{answer_count}} out of {{exam_length}} questions answered. Unanswered questions are shown in red. <p>Click to go to a question.</p></div> <div class="overview-text">{{answer_count}} out of {{exam_length}} questions answered. Unanswered questions are shown in red. <p>Click to go to a question.</p></div>
<div class="sba-finish-list"> <div class="sba-finish-list">
@@ -43,8 +43,8 @@
{% endfor %} {% endfor %}
</div> </div>
<div id="time-details"> <div id="time-details">
Start time: {{cid_user_exam.start_time}}<br/> Start time: {{cid_user_exam.start_time}}<br/>
Last change time: {{cid_user_exam.end_time}} Last change time: {{cid_user_exam.end_time}}
</div> </div>
{% endblock %} {% endblock %}
+1 -1
View File
@@ -3,7 +3,7 @@
{% block navigation %} {% block navigation %}
{{block.super}} {{block.super}}
<br/> <br/>
Exams: {{exam.name}}-> Exams: {{exam}}->
<a href="{% url 'sbas:exam_overview' pk=exam.pk %}">Overview</a> / <a href="{% url 'sbas:exam_overview' pk=exam.pk %}">Overview</a> /
<a href="{% url 'sbas:exam_scores_all' pk=exam.pk %}">Scores</a> / <a href="{% url 'sbas:exam_scores_all' pk=exam.pk %}">Scores</a> /
<a href="{% url 'sbas:exam_cids' exam_id=exam.pk %}">Candidates</a> / <a href="{% url 'sbas:exam_cids' exam_id=exam.pk %}">Candidates</a> /
+38 -38
View File
@@ -1,44 +1,44 @@
{% extends 'sbas/base.html' %} {% extends 'sbas/base.html' %}
{% block content %} {% block content %}
<div class="question"> <div class="question">
<a href="{% url 'sbas:question_update' question.id %}" title="Edit the Question">Edit</a> <a href="{% url 'sbas:question_update' question.id %}" title="Edit the Question">Edit</a>
<a href="{% url 'sbas:question_clone' question.id %}" title="Clone the Question">Clone</a> <a href="{% url 'sbas:question_clone' question.id %}" title="Clone the Question">Clone</a>
<a href="{% url 'sbas:question_delete' pk=question.pk %}" title="Delete the Question">Delete</a> <a href="{% url 'sbas:question_delete' pk=question.pk %}" title="Delete the Question">Delete</a>
<a href="{% url 'admin:sbas_question_change' question.id %}" <a href="{% url 'admin:sbas_question_change' question.id %}"
title="Edit the Question using the admin interface">Admin Edit</a> title="Edit the Question using the admin interface">Admin Edit</a>
<a href="#" onclick="return window.create_popup_window('{% url 'feedback_create' question_type='sbas' pk=question.pk %}')"> Add Note</a> <a href="#" onclick="return window.create_popup_window('{% url 'feedback_create' question_type='sbas' pk=question.pk %}')"> Add Note</a>
<div class="date"> <div class="date">
Created: {{ question.created_date|date:"d/m/Y"}} Created: {{ question.created_date|date:"d/m/Y"}}
</div> </div>
{% autoescape off %} {% autoescape off %}
<span>{{question.stem}}</span> <span>{{question.stem}}</span>
<div> <div>
<ol class="abcde"> <ol class="abcde">
<li>{{ question.a_answer }}</li> <li>{{ question.a_answer }}</li>
<li>{{ question.b_answer }}</li> <li>{{ question.b_answer }}</li>
<li>{{ question.c_answer }}</li> <li>{{ question.c_answer }}</li>
<li>{{ question.d_answer }}</li> <li>{{ question.d_answer }}</li>
<li>{{ question.e_answer }}</li> <li>{{ question.e_answer }}</li>
</ol> </ol>
Best answer: {{ question.best_answer }} ({{question.get_correct_answer_stripped}}) Best answer: {{ question.best_answer }} ({{question.get_correct_answer_stripped}})
</div> </div>
{% endautoescape %} {% endautoescape %}
<div> <div>
Examinations: {% for exam in question.exams.all %} Examinations: {% for exam in question.exams.all %}
<a href="{% url 'sbas:exam_overview' pk=exam.pk %}">{{ exam.name }}</a> <a href="{% url 'sbas:exam_overview' pk=exam.pk %}">{{ exam }}</a>
{% endfor %} {% endfor %}
</div> </div>
<div> <div>
Category: {{ question.category }} Category: {{ question.category }}
</div> </div>
<div> <div>
Author: {% for user in question.author.all %} Author: {% for user in question.author.all %}
{{ author }}, {{ author }},
{% endfor %} {% endfor %}
</div> </div>
{% include 'question_notes.html' %} {% include 'question_notes.html' %}
</div> </div>
{% endblock %} {% endblock %}
+2 -2
View File
@@ -20,7 +20,7 @@
<h4>{{exam_type|title}}</h4> <h4>{{exam_type|title}}</h4>
<ul class='{{exam_type|lower}}'> <ul class='{{exam_type|lower}}'>
{% for exam in exams %} {% for exam in exams %}
<li class="exam" data-exam-id="{{exam.pk}}">{{exam.name}} <li class="exam" data-exam-id="{{exam.pk}}">{{exam}}
{% if exam.active %} {% if exam.active %}
<a href="{{exam.get_take_url}}?cid={{cid}}&passcode={{passcode}}" target="_blank" title="Click to take exam"> <a href="{{exam.get_take_url}}?cid={{cid}}&passcode={{passcode}}" target="_blank" title="Click to take exam">
<button class="small-url-button start-button">Start</button> <button class="small-url-button start-button">Start</button>
@@ -47,7 +47,7 @@
<h4>{{exam_type|title}}</h4> <h4>{{exam_type|title}}</h4>
<ul class='{{exam_type|lower}}'> <ul class='{{exam_type|lower}}'>
{% for exam in exams %} {% for exam in exams %}
<li class="exam" data-exam-id="{{exam.pk}}"><a href="{% url exam_type|add:':exam_scores_cid_user' pk=exam.pk cid=cid passcode=passcode %}">{{exam.name}}</a> {% if exam.active %}[Active]{% endif %} {% if exam.publish_results %}[Results Published]{% endif %}</li> <li class="exam" data-exam-id="{{exam.pk}}"><a href="{% url exam_type|add:':exam_scores_cid_user' pk=exam.pk cid=cid passcode=passcode %}">{{exam}}</a> {% if exam.active %}[Active]{% endif %} {% if exam.publish_results %}[Results Published]{% endif %}</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
+2 -2
View File
@@ -4,9 +4,9 @@
{% load thumbnail %} {% load thumbnail %}
<div class="{{app_name}}"> <div class="{{app_name}}">
<h1>Exam: {{ exam.name }}</h1> <h1>Exam: {{ exam }}</h1>
{% include "generic/exam_cids.html" %} {% include "generic/exam_cids.html" %}
</div> </div>
{% endblock %} {% endblock %}
+2 -2
View File
@@ -3,9 +3,9 @@
{% block content %} {% block content %}
<div class="{{app_name}}"> <div class="{{app_name}}">
<h1>Exam: {{ exam.name }}</h1> <h1>Exam: {{ exam }}</h1>
{% include "generic/exam_cids_edit.html" %} {% include "generic/exam_cids_edit.html" %}
</div> </div>
{% endblock %} {% endblock %}
+4 -4
View File
@@ -1,8 +1,8 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% block content %}
<div class=""> <div class="">
<h2>{{exam.name}}</h2> <h2>{{exam}}</h2>
Exam is currently inactive. Exam is currently inactive.
</div> </div>
{% endblock %} {% endblock %}
+2 -2
View File
@@ -8,7 +8,7 @@
{% for exam in exams %} {% for exam in exams %}
{% if exam.active %} {% if exam.active %}
<li class="exam-item"> <li class="exam-item">
<a href="{% url app_name|add:':exam_overview' pk=exam.pk %}" class="flex-col-2 exam-name">{{exam.name}}</a> <a href="{% url app_name|add:':exam_overview' pk=exam.pk %}" class="flex-col-2 exam-name">{{exam}}</a>
{% if marking %}<a href="{% url app_name|add:':mark_overview' pk=exam.pk %}" class="flex-col-half">Mark</a>{% endif %} {% if marking %}<a href="{% url app_name|add:':mark_overview' pk=exam.pk %}" class="flex-col-half">Mark</a>{% endif %}
<span class="flex-col"> <span class="flex-col">
<a href="{% url app_name|add:':exam_cids' exam_id=exam.pk %}">Candidates</a> <span class="candidate-counts">[<span title="Number of active CID users"> <a href="{% url app_name|add:':exam_cids' exam_id=exam.pk %}">Candidates</a> <span class="candidate-counts">[<span title="Number of active CID users">
@@ -35,7 +35,7 @@
{% for exam in exams %} {% for exam in exams %}
{% if not exam.active %} {% if not exam.active %}
<li class="exam-item"> <li class="exam-item">
<a href="{% url app_name|add:':exam_overview' pk=exam.pk %}" class="flex-col-2 exam-name">{{exam.name}}</a> <a href="{% url app_name|add:':exam_overview' pk=exam.pk %}" class="flex-col-2 exam-name">{{exam}}</a>
{% if marking %}<a href="{% url app_name|add:':mark_overview' pk=exam.pk %}" class="flex-col-half">Mark</a>{% endif %} {% if marking %}<a href="{% url app_name|add:':mark_overview' pk=exam.pk %}" class="flex-col-half">Mark</a>{% endif %}
<span class="flex-col"> <span class="flex-col">
<a href="{% url app_name|add:':exam_cids' exam_id=exam.pk %}">Candidates</a> <a href="{% url app_name|add:':exam_cids' exam_id=exam.pk %}">Candidates</a>
+1 -1
View File
@@ -1,7 +1,7 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% block content %}
<h2>{{exam.name}}: Stats</h2> <h2>{{exam}}: Stats</h2>
{% if exam.stats_candidates < 4 %} {% if exam.stats_candidates < 4 %}
Not enough data points... Not enough data points...
{% else %} {% else %}
+2 -2
View File
@@ -3,9 +3,9 @@
{% block content %} {% block content %}
<div class="{{app_name}}"> <div class="{{app_name}}">
<h1>Exam: {{ exam.name }}</h1> <h1>Exam: {{ exam }}</h1>
{% include "generic/exam_users_edit.html" %} {% include "generic/exam_users_edit.html" %}
</div> </div>
{% endblock %} {% endblock %}
+7 -7
View File
@@ -1,18 +1,18 @@
{% if view_all_results %} {% if view_all_results %}
<div class="alert alert-info" role="alert"> <div class="alert alert-info" role="alert">
Exam state: Exam state:
{% if exam.active %} {% if exam.active %}
This exam is available to take. This exam is available to take.
{% else %} {% else %}
This exam is NOT available to take. This exam is NOT available to take.
{% endif %} {% endif %}
{% if exam.publish_results %} {% if exam.publish_results %}
Results are published. Results are published.
{% else %} {% else %}
Results are NOT published. Results are NOT published.
{% endif %} {% endif %}
@@ -24,6 +24,6 @@
<div class="alert alert-info" role="alert">Results are not currently published. You can see your own answers below.</a></div> <div class="alert alert-info" role="alert">Results are not currently published. You can see your own answers below.</a></div>
{% endif %} {% endif %}
{% endif %} {% endif %}
<h2>Exam: {{ exam.name }}</h2> <h2>Exam: {{ exam }}</h2>
<h3>Candidate: {{ cid|default_if_none:request.user.username }}</h3> <h3>Candidate: {{ cid|default_if_none:request.user.username }}</h3>
Answers: Answers:
+2 -2
View File
@@ -20,7 +20,7 @@
<h4>{{exam_type|title}}</h4> <h4>{{exam_type|title}}</h4>
<ul class='{{exam_type|lower}}'> <ul class='{{exam_type|lower}}'>
{% for exam in exams %} {% for exam in exams %}
<li class="exam" data-exam-id="{{exam.pk}}">{{exam.name}} <li class="exam" data-exam-id="{{exam.pk}}">{{exam}}
{% if exam.active %} {% if exam.active %}
<a href="{{exam.get_take_url}}" target="_blank" title="Click to take exam"> <a href="{{exam.get_take_url}}" target="_blank" title="Click to take exam">
<button class="small-url-button start-button">Start</button> <button class="small-url-button start-button">Start</button>
@@ -55,7 +55,7 @@
<a href= "{% url exam_type|add:':exam_scores_user' pk=exam.pk %}" title="Click to view results"> <a href= "{% url exam_type|add:':exam_scores_user' pk=exam.pk %}" title="Click to view results">
{% endif %} {% endif %}
{{exam.name}}</a> {% if exam.active %}[Active]{% endif %} {% if exam.publish_results %}[Results Published]{% endif %}</li> {{exam}}</a> {% if exam.active %}[Active]{% endif %} {% if exam.publish_results %}[Results Published]{% endif %}</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}