Add mark2 overview page and update navigation for improved marking workflow
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
<a href="{% url 'anatomy:exam_overview' pk=exam.pk %}">Overview</a> /
|
||||
{% if exam.exam_mode %}
|
||||
<a href="{% url 'anatomy:mark_overview' pk=exam.pk %}">Mark</a> /
|
||||
<a href="{% url 'anatomy:mark2_overview' pk=exam.pk %}">Mark2</a> /
|
||||
<a href="{% url 'anatomy:exam_scores_all' pk=exam.pk %}">Scores</a> /
|
||||
<a href="{% url 'anatomy:exam_cids' exam_id=exam.pk %}">Candidates</a> /
|
||||
<a href="{% url 'anatomy:exam_stats' exam_id=exam.pk %}">Stats</a> /
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
{% extends 'anatomy/exams.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="anatomy">
|
||||
<h2>Mark2: Marking exam: {{ exam }}</h2>
|
||||
Use the improved HTMX marking UI by clicking into a question below.
|
||||
|
||||
<div>
|
||||
<button class="show-all-button">Show all</button><button class="show-unmarked-button">Show unmarked</button>
|
||||
</div>
|
||||
<div id="stark-marking-button"><a href="{% url 'anatomy:mark2' exam_pk=exam.pk sk=0 %}"><button>Click here to start mark2</button></a></div>
|
||||
|
||||
<ul id="question-mark-list">
|
||||
{% for question, unmarked_count, unmarked_count2 in question_unmarked_map %}
|
||||
<li data-markcount={{unmarked_count}} {% if unmarked_count %}class="unmarked" {% endif %}><a href="{% url 'anatomy:mark2' exam_pk=exam.pk sk=forloop.counter0 %}">Question {{forloop.counter }}:
|
||||
{{ question }}</a><br />Unmarked answers: {{ unmarked_count }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -109,6 +109,7 @@ urlpatterns = [
|
||||
),
|
||||
# New improved marking UI (mark2) and small toggle endpoint used by JS/HTMX
|
||||
path("exam/<int:exam_pk>/<int:sk>/mark2", views.mark2, name="mark2"),
|
||||
path("exam/<int:pk>/mark2", views.mark2_overview, name="mark2_overview"),
|
||||
path("exam/mark2/toggle", views.mark2_toggle_answer, name="mark2_toggle_answer"),
|
||||
path("exam/<int:exam_pk>/<int:sk>/mark2/exam_marked", views.mark2_exam_marked, name="mark2_exam_marked"),
|
||||
path("question/<int:pk>/mark2/question_marked", views.mark2_question_marked, name="mark2_question_marked"),
|
||||
|
||||
@@ -15,6 +15,7 @@ from django.views.generic.edit import CreateView, UpdateView, DeleteView
|
||||
from django.views.generic import ListView
|
||||
|
||||
from django.db.models.functions import Lower
|
||||
from django.db.models import Prefetch
|
||||
|
||||
from django.core.cache import cache
|
||||
|
||||
@@ -780,6 +781,65 @@ def mark2(request, exam_pk, sk, unmarked_exam_answers_only=True, review=False):
|
||||
return render(request, "anatomy/mark2.html", context)
|
||||
|
||||
|
||||
@login_required
|
||||
def mark2_overview(request, pk):
|
||||
"""Overview page for mark2 workflow: lists questions and unmarked counts and links into mark2."""
|
||||
exam = get_object_or_404(Exam, pk=pk)
|
||||
|
||||
if not exam.exam_mode:
|
||||
raise Http404("Packet not in exam mode")
|
||||
|
||||
# Only allow authors or designated markers
|
||||
if request.user not in exam.author.all():
|
||||
if not GenericExamViews.check_user_marker_access(request.user, pk):
|
||||
raise PermissionDenied
|
||||
|
||||
# For anatomy prefer prefetch similar to generic.mark_overview
|
||||
questions = (
|
||||
exam.exam_questions.select_related(
|
||||
"modality",
|
||||
"structure",
|
||||
"body_part",
|
||||
"region",
|
||||
"examination",
|
||||
"question_type",
|
||||
)
|
||||
.all()
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
"answers",
|
||||
queryset=Answer.objects.filter(proposed=False, status=Answer.MarkOptions.CORRECT),
|
||||
to_attr="prefetched_primary_answer",
|
||||
),
|
||||
)
|
||||
.order_by("examquestiondetail__sort_order")
|
||||
)
|
||||
|
||||
# Handle double marking which needs per-marker counts
|
||||
try:
|
||||
if exam.double_mark:
|
||||
question_unmarked_map = []
|
||||
for q in questions:
|
||||
question_unmarked_map.append(
|
||||
(
|
||||
q,
|
||||
int(q.get_unmarked_user_answer_count(exam_pk=exam.pk)),
|
||||
int(q.get_unmarked_user_answer_count(exam_pk=exam.pk, marker=request.user)),
|
||||
)
|
||||
)
|
||||
|
||||
return render(request, "anatomy/mark2_overview.html", {"exam": exam, "question_unmarked_map": question_unmarked_map})
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
question_unmarked_map = []
|
||||
for q in questions:
|
||||
count = int(q.get_unmarked_user_answer_count(exam_pk=exam.pk))
|
||||
question_unmarked_map.append((q, count, count))
|
||||
|
||||
return render(request, "anatomy/mark2_overview.html", {"exam": exam, "question_unmarked_map": question_unmarked_map})
|
||||
|
||||
|
||||
@login_required
|
||||
def mark2_toggle_answer(request):
|
||||
"""Endpoint to toggle/set a single answer mark quickly.
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
<small class="text-muted">Authors: {{ exam.get_authors }}</small>
|
||||
{% if exam.exam_mode %}
|
||||
{% if app_name in "rapids longs anatomy" %}
|
||||
{% if request.user.is_staff %}<a href="{% url app_name|add:':mark_overview' pk=exam.pk %}">Mark answers</a>{% endif %}
|
||||
{% if request.user.is_staff %}
|
||||
<a href="{% url app_name|add:':mark_overview' pk=exam.pk %}">Mark answers</a>
|
||||
{% if app_name == 'anatomy' %} / <a href="{% url 'anatomy:mark2_overview' pk=exam.pk %}">Mark (mark2)</a>{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if request.user.is_staff %}<a href="{% url app_name|add:':exam_scores_all' pk=exam.pk %}">Scores</a>{% endif %}
|
||||
{% endif %}
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
<a href='{% url "generic:examcollection_detail" exam.examcollection_id %}' title="This exam is part of the collection {{exam.examcollection.name}}"><i class="bi bi-collection"></i></a>
|
||||
{% endif %}
|
||||
</span>
|
||||
{% 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>
|
||||
{% if app_name == 'anatomy' %}<a href="{% url 'anatomy:mark2_overview' pk=exam.pk %}" class="flex-col-half">Mark2</a>{% endif %}
|
||||
{% endif %}
|
||||
<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">
|
||||
{{exam.valid_cid_users.count}}
|
||||
|
||||
Reference in New Issue
Block a user