feat: enhance exam user status handling and add autosave verification in tests
This commit is contained in:
@@ -37,7 +37,13 @@
|
|||||||
<td class="text-nowrap small {% if user_data.in_exam %}text-muted{% else %}text-dark{% endif %}">{{ user_data.end_time }}</td>
|
<td class="text-nowrap small {% if user_data.in_exam %}text-muted{% else %}text-dark{% endif %}">{{ user_data.end_time }}</td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group" role="group">
|
||||||
<button class="btn btn-sm btn-outline-secondary" title="View details" hx-get="{% url exam.get_app_name|add:':exam_user_status' exam.id %}?cid={{ user_data.cid_user }}" hx-target="#history-modal .modal-body" data-bs-toggle="modal" data-bs-target="#history-modal"><i class="bi bi-eye"></i></button>
|
{% if user_data.cid_user %}
|
||||||
|
<button class="btn btn-sm btn-outline-secondary" title="View details" hx-get="{% url exam.get_app_name|add:':exam_user_status' exam.id %}?cid={{ user_data.cid_user.cid }}" hx-target="#history-modal .modal-body" data-bs-toggle="modal" data-bs-target="#history-modal"><i class="bi bi-eye"></i></button>
|
||||||
|
<a class="btn btn-sm btn-outline-success" href="{% url exam.get_app_name|add:':exam_scores_cid_user_admin' exam.id user_data.cid_user.cid %}" target="_blank" rel="noopener" title="View candidate answers"><i class="bi bi-file-earmark-text"></i></a>
|
||||||
|
{% else %}
|
||||||
|
<button class="btn btn-sm btn-outline-secondary" title="View details" hx-get="{% url exam.get_app_name|add:':exam_user_status' exam.id %}?user_id={{ user_data.user_user.id }}" hx-target="#history-modal .modal-body" data-bs-toggle="modal" data-bs-target="#history-modal"><i class="bi bi-eye"></i></button>
|
||||||
|
<a class="btn btn-sm btn-outline-success" href="{% url exam.get_app_name|add:':exam_scores_user_admin' exam.id user_data.user_user.id %}" target="_blank" rel="noopener" title="View candidate answers"><i class="bi bi-file-earmark-text"></i></a>
|
||||||
|
{% endif %}
|
||||||
{% if request.user.is_superuser or request.user.is_staff %}
|
{% if request.user.is_superuser or request.user.is_staff %}
|
||||||
<a class="btn btn-sm btn-outline-primary" href="{% url 'admin:generic_ciduserexam_change' user_data.pk %}" target="_blank" rel="noopener" title="Edit submission in admin"><i class="bi bi-pencil-square"></i></a>
|
<a class="btn btn-sm btn-outline-primary" href="{% url 'admin:generic_ciduserexam_change' user_data.pk %}" target="_blank" rel="noopener" title="Edit submission in admin"><i class="bi bi-pencil-square"></i></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
+22
-2
@@ -2639,13 +2639,27 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
return self.exam_user_status(request, pk, user_id=user_id)
|
return self.exam_user_status(request, pk, user_id=user_id)
|
||||||
|
|
||||||
def exam_user_status(self, request, pk, cid=None, user_id=None):
|
def exam_user_status(self, request, pk, cid=None, user_id=None):
|
||||||
# TODO: add filtering by user / cid
|
|
||||||
exam = get_object_or_404(self.Exam, pk=pk)
|
exam = get_object_or_404(self.Exam, pk=pk)
|
||||||
|
|
||||||
# Restrict just to exam authors
|
# Restrict just to exam authors
|
||||||
if request.user not in exam.author.all():
|
if request.user not in exam.author.all():
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
|
# Robustly parse parameters from GET query string
|
||||||
|
get_cid = request.GET.get("cid")
|
||||||
|
get_user_id = request.GET.get("user_id")
|
||||||
|
|
||||||
|
if get_cid not in (None, "", "None"):
|
||||||
|
try:
|
||||||
|
cid = int(get_cid)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
if get_user_id not in (None, "", "None"):
|
||||||
|
try:
|
||||||
|
user_id = int(get_user_id)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
if cid is not None:
|
if cid is not None:
|
||||||
statuses = exam.exam_user_status.filter(cid_user_exam__cid_user__cid=cid)
|
statuses = exam.exam_user_status.filter(cid_user_exam__cid_user__cid=cid)
|
||||||
elif user_id is not None:
|
elif user_id is not None:
|
||||||
@@ -3477,7 +3491,13 @@ class ExamViews(View, LoginRequiredMixin):
|
|||||||
cid_user=c, start_time=t
|
cid_user=c, start_time=t
|
||||||
)
|
)
|
||||||
in_progress = request.POST.get("in_progress") == "true"
|
in_progress = request.POST.get("in_progress") == "true"
|
||||||
if not in_progress:
|
if in_progress:
|
||||||
|
exam.exam_user_status.create(
|
||||||
|
cid_user_exam=cid_user_exam,
|
||||||
|
status="autosaved",
|
||||||
|
extra="autosaved {} answers".format(n),
|
||||||
|
)
|
||||||
|
else:
|
||||||
exam.exam_user_status.create(
|
exam.exam_user_status.create(
|
||||||
cid_user_exam=cid_user_exam,
|
cid_user_exam=cid_user_exam,
|
||||||
status="submitted",
|
status="submitted",
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ def test_autosubmit_in_progress(client, test_setup):
|
|||||||
assert cid_user_exam.end_time is None
|
assert cid_user_exam.end_time is None
|
||||||
assert cid_user_exam.completed is False
|
assert cid_user_exam.completed is False
|
||||||
assert not ExamUserStatus.objects.filter(cid_user_exam=cid_user_exam, status="submitted").exists()
|
assert not ExamUserStatus.objects.filter(cid_user_exam=cid_user_exam, status="submitted").exists()
|
||||||
|
assert ExamUserStatus.objects.filter(cid_user_exam=cid_user_exam, status="autosaved").exists()
|
||||||
|
|
||||||
def test_final_submit(client, test_setup):
|
def test_final_submit(client, test_setup):
|
||||||
exam = test_setup["exam"]
|
exam = test_setup["exam"]
|
||||||
|
|||||||
Reference in New Issue
Block a user