Implement edit answer functionality with HTMX support; add new endpoint and template for editing stored answers in the marking UI.

This commit is contained in:
Ross
2025-11-11 13:01:51 +00:00
parent 14a54dfa8b
commit 796ac3fb84
4 changed files with 174 additions and 8 deletions
+86 -1
View File
@@ -818,6 +818,24 @@ def mark2_toggle_answer(request):
"incorrect": Answer.MarkOptions.INCORRECT,
}
# Support clearing a stored answer (delete) via 'clear'
exam_pk = request.POST.get('exam_pk')
sk = request.POST.get('sk')
if newmark == 'clear':
a = Answer.objects.filter(answer_compare__iexact=answer_text, question_id=question.pk).first()
if a is not None:
# permission: ensure user can edit this answer
if not a.can_edit(request.user):
return JsonResponse({"status": "error", "message": "forbidden"}, status=403)
a.delete()
if request.htmx and exam_pk and sk is not None:
try:
return mark2_exam_marked(request, int(exam_pk), int(sk))
except Exception:
return JsonResponse({"status": "ok"})
return JsonResponse({"status": "ok"})
if newmark not in mark_map:
return JsonResponse({"status": "error", "message": "invalid mark"}, status=400)
@@ -833,6 +851,12 @@ def mark2_toggle_answer(request):
a.status = status_val
a.save()
if request.htmx and exam_pk and sk is not None:
try:
return mark2_exam_marked(request, int(exam_pk), int(sk))
except Exception:
return JsonResponse({"status": "ok"})
return JsonResponse({"status": "ok"})
@@ -879,10 +903,71 @@ def mark2_exam_marked(request, exam_pk, sk):
else:
items.sort(key=lambda x: x.get('count', 0), reverse=True)
context = {'exam': exam, 'question': question, 'items': items}
context = {'exam': exam, 'question': question, 'items': items, 'sk': sk}
return render(request, 'anatomy/partials/mark2_exam_marked_fragment.html', context)
@login_required
def mark2_edit_answer(request):
"""HTMX-friendly endpoint to edit/create a stored Answer for a question.
GET: returns a small form fragment.
POST: updates/creates the Answer and, if exam_pk/sk provided, returns the
refreshed exam-marked fragment so the UI updates in-place.
"""
if request.method == 'GET' and request.htmx:
question_pk = request.GET.get('question_pk')
original = request.GET.get('original', '')
exam_pk = request.GET.get('exam_pk')
sk = request.GET.get('sk')
question = get_object_or_404(AnatomyQuestion, pk=question_pk)
# Try to find an existing Answer by compare
existing = question.answers.filter(answer_compare__iexact=original).first()
context = {
'question': question,
'original': original,
'existing': existing,
'exam_pk': exam_pk,
'sk': sk,
}
return render(request, 'anatomy/partials/mark2_edit_answer_fragment.html', context)
if request.method == 'POST' and request.htmx:
question_pk = request.POST.get('question_pk')
original = request.POST.get('original', '')
new_text = request.POST.get('new_answer', '').strip()
exam_pk = request.POST.get('exam_pk')
sk = request.POST.get('sk')
if not question_pk or not new_text:
return HttpResponse('Missing parameters', status=400)
question = get_object_or_404(AnatomyQuestion, pk=question_pk)
a = question.answers.filter(answer_compare__iexact=original).first()
if a is None:
a = Answer()
a.question = question
a.answer = new_text
else:
a.answer = new_text
a.save()
# If we have exam context, refresh the exam-marked fragment for that question
if exam_pk and sk is not None:
# delegate to mark2_exam_marked to re-render the card
try:
return mark2_exam_marked(request, int(exam_pk), int(sk))
except Exception:
return HttpResponse('OK')
return HttpResponse('OK')
# Fallback: forbidden for non-HTMX or other methods
raise PermissionDenied()
@login_required
def mark2_question_marked(request, pk):
"""Return a partial listing of all stored Answer choices for this question (grouped by status)."""