Enhance form rendering with crispy forms and improve answer timestamp handling in collection views

This commit is contained in:
Ross
2025-10-13 13:22:26 +01:00
parent ed4bd95955
commit a3712959ec
3 changed files with 34 additions and 19 deletions
@@ -1,4 +1,5 @@
{% extends 'atlas/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<span class="collection-name-blend">Collection: {{collection}}</span>
@@ -218,7 +219,7 @@
{{form.json.errors}}
<div class="form-contents">
<fieldset {% if question_completed %}disabled="disabled"{% endif %}>
{{form}}
{{form | crispy}}
</fieldset>
</div>
@@ -345,6 +346,24 @@
// Question time limit countdown + auto-submit
$(function () {
function lockQuestion() {
// Only disable save buttons to prevent further saves
$form = $('form.post-form');
var $saveBtns = $form.find('button[name="save"], #id_answer');
if ($saveBtns.length) {
$saveBtns.prop('disabled', true);
}
// Visual feedback: set timer to Locked and progress to red
$progressInner = $('#question-timer-progress-inner');
$('#question-timer').text('Locked');
$progressInner.css('background', '#dc3545');
$progressInner.css('width', '0%');
$("#question-timer-progress-outer").hide();
}
try {
var timeLimit = {{ collection.question_time_limit|default:'null' }};
var questionCompleted = {{ question_completed|yesno:"true,false" }};
@@ -354,6 +373,15 @@
if (!timeLimit || questionCompleted) {
return;
}
{% if answer %}
if ({{answer.completed|yesno:"true,false"}}) {
lockQuestion();
console.debug('Timer: answer already completed, aborting timer init');
return;
}
{% endif %}
var $timer = $('#question-timer');
var $form = $('form.post-form');
@@ -434,16 +462,7 @@
console.debug('No JSON response from timed_out request', e);
}
// Only disable save buttons to prevent further saves
var $saveBtns = $form.find('button[name="save"], #id_answer');
if ($saveBtns.length) {
$saveBtns.prop('disabled', true);
}
// Visual feedback: set timer to Locked and progress to red
$('#question-timer').text('Locked');
$progressInner.css('background', '#dc3545');
$progressInner.css('width', '0%');
lockQuestion();
var msg = 'Answer auto-submitted';
if (resp && resp.submitted_at) {
@@ -34,13 +34,13 @@
<ul>
{% for cidexam in cidexams %}
<li id="cid-history-{{ cidexam.cid_user.pk }}">
<b><a href="{% url 'atlas:collection_history_ciduser' collection.pk cidexam.cid_user.pk %}">{{cidexam.cid_user}}</a><b><br/>
<b><a href="{% url 'atlas:collection_history_ciduser' collection.pk cidexam.cid_user.cid %}">{{cidexam.cid_user}}</a><b><br/>
Completed: {{cidexam.completed}}<br/>
Started: {{cidexam.start_time}}, Ended: {{cidexam.end_time}}<br/>
<button
hx-post="{% url 'atlas:collection_reset_answers_ciduser' collection.pk cidexam.cid_user.pk %}"
hx-target="#cid-history-{{ cidexam.cid_user.pk }}"
hx-post="{% url 'atlas:collection_reset_answers_ciduser' collection.pk cidexam.cid_user.cid %}"
hx-target="#cid-history-{{ cidexam.cid_user.cid }}"
hx-swap="outerHTML"
hx-confirm="Are you sure you want to delete this CID user's collection history?"
class="btn btn-danger btn-sm remove-button">
+1 -5
View File
@@ -2947,11 +2947,7 @@ def collection_case_view_take(
"cid_user_exam": cid_user_exam,
"question_completed": question_completed,
"self_review": self_review,
# Provide a canonical start timestamp (prefer answer.started_at, then cid_user_exam.start_time)
"answer_started_at_iso": (
(answer.started_at.isoformat() if getattr(answer, 'started_at', None) else None)
or (cid_user_exam.start_time.isoformat() if getattr(cid_user_exam, 'start_time', None) else None)
),
"answer_started_at_iso": answer.started_at.isoformat() if answer and getattr(answer, 'started_at', None) else None,
},
)