From ed4bd95955042556b8e88317bfbf2cea919f9ea6 Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 13 Oct 2025 11:48:13 +0100 Subject: [PATCH] Refactor self-review display logic and enhance user answer feedback in collection templates; improve form serialization for timeout handling --- .../atlas/collection_case_view_take.html | 91 ++++++++++++++----- .../atlas/collection_history_user.html | 10 +- atlas/views.py | 1 - 3 files changed, 72 insertions(+), 30 deletions(-) diff --git a/atlas/templates/atlas/collection_case_view_take.html b/atlas/templates/atlas/collection_case_view_take.html index 6785da09..856353eb 100644 --- a/atlas/templates/atlas/collection_case_view_take.html +++ b/atlas/templates/atlas/collection_case_view_take.html @@ -221,25 +221,28 @@ {{form}} -
- {% if collection.self_review %} -

- -

- {% if self_review %} -

Self Feedback

- {% for review in self_review %} - {{review.get_display_block}} + {% if question_completed %} +
+ {% if collection.self_review %} +

+ +

+ {% if self_review %} +

Self Feedback

- {% endfor %} + {% for review in self_review %} + {{review.get_display_block}} + + {% endfor %} + {% endif %} + {% else %} +

Answer score: {{answer.score}}

+ Answer feedback: {{answer.feedback|safe}} +
{% endif %} - {% else %} -

Answer score: {{answer.score}}

- Answer feedback: {{answer.feedback|safe}} -
- {% endif %} -
+
+ {% endif %} {% endif %} {% if previous %} @@ -458,14 +461,54 @@ }; htmx.on('htmx:afterRequest', onAfter); - htmx.ajax('POST', window.location.href, { - values: { timed_out: '1' }, - swap: 'none', - headers: { - 'X-CSRFToken': document.querySelector('input[name="csrfmiddlewaretoken"]').value, - }, - target: "#timer-htmx-target", - }); + // Serialize the entire form so the server receives the user's answers + // along with the timed_out flag. This ensures the form.save() path + // can validate and persist the submitted answers on timeout. + (function(){ + var formValues = {}; + try { + $.each($form.serializeArray(), function(i, field) { + if (formValues[field.name] !== undefined) { + if (!Array.isArray(formValues[field.name])) { + formValues[field.name] = [formValues[field.name]]; + } + formValues[field.name].push(field.value); + } else { + formValues[field.name] = field.value; + } + }); + } catch (e) { + console.debug('Failed to serialize form with jQuery, falling back to manual collection', e); + // Fallback: try to collect inputs manually + var inputs = $form.find('input, textarea, select').not(':disabled'); + inputs.each(function () { + var $el = $(this); + var name = $el.attr('name'); + if (!name) return; + var val = $el.val(); + if (formValues[name] !== undefined) { + if (!Array.isArray(formValues[name])) { + formValues[name] = [formValues[name]]; + } + formValues[name].push(val); + } else { + formValues[name] = val; + } + }); + } + + // Ensure the timed_out flag is included + formValues['timed_out'] = '1'; + + htmx.ajax('POST', window.location.href, { + values: formValues, + swap: 'none', + headers: { + 'X-CSRFToken': document.querySelector('input[name="csrfmiddlewaretoken"]').value, + }, + target: "#timer-htmx-target", + }); + })(); } else { $timer.text(formatTime(remaining)); updateProgress(); diff --git a/atlas/templates/atlas/collection_history_user.html b/atlas/templates/atlas/collection_history_user.html index c2c239c3..afaf10d7 100644 --- a/atlas/templates/atlas/collection_history_user.html +++ b/atlas/templates/atlas/collection_history_user.html @@ -10,21 +10,20 @@
  • {{forloop.counter}} / Case: {{casedetail.case.title}}

    - {{user_answer.started_at}} - {{user_answer.submitted_at}} + Question started: {{user_answer.started_at}} - Answer submitted: {{user_answer.submitted_at}} {% if request.user.is_superuser and user_answer %}  (Edit in admin) {% endif %}
    +
    {% if not user_answer %} Case not answered. {% else %} - - -
    + User answer: +
    {% if user_answer.answer %} {{user_answer.answer}} - {% else %} {{user_answer.json_answer}} {% for value, user_answer, correct_answer, answer_is_correct, automark in user_answer.get_correct_json_answers %} @@ -57,6 +56,7 @@ {% endfor %} {% endif %} +
    {% endif %} diff --git a/atlas/views.py b/atlas/views.py index 312f9aab..a6bafa23 100755 --- a/atlas/views.py +++ b/atlas/views.py @@ -2833,7 +2833,6 @@ def collection_case_view_take( or getattr(request, 'htmx', False) ) if is_ajax: - from django.http import JsonResponse return JsonResponse( { 'status': 'ok',