improve case user answer management (and fix small bug)
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.2 on 2024-11-18 09:59
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('atlas', '0063_casecollection_results_supervisor_visible'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='casecollection',
|
||||
name='exam_open_access',
|
||||
field=models.BooleanField(default=False, help_text='Set to true if you want any registered user to be able to take the exam.'),
|
||||
),
|
||||
]
|
||||
@@ -33,6 +33,7 @@
|
||||
<p>View as a viva collection <a href='{% url "atlas:collection_viva" collection.pk %}'>here</a>
|
||||
{% else %}
|
||||
<p>This collection will be available to view/take <a href='{{collection.get_take_url}}'>here</a> (when active)
|
||||
<p>Review collection <a href='{% url "atlas:collection_viva" collection.pk %}'>here</a>
|
||||
{% endif %}
|
||||
|
||||
{% if can_edit %}
|
||||
@@ -59,6 +60,13 @@
|
||||
hx-swap="outerHTML"
|
||||
hx-confirm="Are you sure you want to reset all answers? This action cannot be undone."
|
||||
>Reset all answers</button>
|
||||
|
||||
<button title="This will specific user answers and attempts"
|
||||
hx-post="{% url 'atlas:collection_reset_answers_user_list' collection.pk %}"
|
||||
hx-swap="innerHTML"
|
||||
hx-target="#user-list"
|
||||
>Reset user answers</button>
|
||||
<div id="user-list"></div>
|
||||
|
||||
</details>
|
||||
{% endif %}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
{% for cid_user_exam in cid_users %}
|
||||
<button title="This will clear the user answers and attempts"
|
||||
hx-post="{% url 'atlas:collection_reset_answers_user' collection.pk cid_user_exam.user_user.id %}"
|
||||
hx-swap="outerHTML"
|
||||
hx-confirm="Are you sure you want to reset answers for the user? This action cannot be undone."
|
||||
>{{cid_user_exam.user_user}}</button>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
@@ -58,12 +58,14 @@
|
||||
|
||||
<div class="sticky-top">
|
||||
<h3>Current Case</h3>
|
||||
<div id="loading-case">Waiting for case to load in linked window.<br/> If you are seeing this message you probably need to open the viewer window and reload the case.</div>
|
||||
<div id="current-case-title">None</div>
|
||||
<div id="current-case-series"></div>
|
||||
<div id="current-case-history"></div>
|
||||
<div id="current-case-discussion"></div>
|
||||
<div id="current-case-report"></div>
|
||||
<div id="case-details">
|
||||
<div id="loading-case">Waiting for case to load in linked window.<br/> If you are seeing this message you probably need to open the viewer window and reload the case.</div>
|
||||
<div id="current-case-title">None</div>
|
||||
<div id="current-case-series"></div>
|
||||
<div id="current-case-history"></div>
|
||||
<div id="current-case-discussion"></div>
|
||||
<div id="current-case-report"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<iframe id="viewer" style="width: 100%; height: 500px; border: none"></iframe>
|
||||
@@ -106,16 +108,16 @@
|
||||
|
||||
$('#loading-case').show()
|
||||
$("#open-viewer").addClass("flash-button");
|
||||
$('#current-case-title').text("Case: "+c.data('title'));
|
||||
$("#current-case-history").text("History: "+case_details['history']);
|
||||
$("#current-case-discussion").text("Discussion: "+case_details['discussion']);
|
||||
$("#current-case-report").text("Report: "+case_details['report']);
|
||||
$('#current-case-title').html("<span class='title'>Case:</span> "+c.data('title'));
|
||||
$("#current-case-history").html("<span class='title'>History:</span> "+case_details['history']);
|
||||
$("#current-case-discussion").html("<span class='title'>Discussion:</span> "+case_details['discussion']);
|
||||
$("#current-case-report").html("<span class='title'>Report:</span> "+case_details['report']);
|
||||
|
||||
console.log($(this).data('type'))
|
||||
if ($(this).data('type') == 'case') {
|
||||
$('#current-case-series').text("Series: All");
|
||||
$('#current-case-series').html("<span class='title'>Series:</span> All");
|
||||
} else {
|
||||
$('#current-case-series').text("Series: " + $(this).data('series'));
|
||||
$('#current-case-series').html("<span class='title'>Series:</span> " + $(this).data('series'));
|
||||
}
|
||||
bc.postMessage({"type": "open", "url" : url});
|
||||
//if (win2 == false || win2.closed) {
|
||||
@@ -153,25 +155,33 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
|
||||
|
||||
<style type="text/css">
|
||||
#loading-case {
|
||||
display: none;
|
||||
color: red;
|
||||
}
|
||||
@keyframes glowing {
|
||||
0% {
|
||||
box-shadow: 0 0 20px #a600ff;
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 40px #52057b;
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 20px #a600ff;
|
||||
}
|
||||
}
|
||||
.flash-button {
|
||||
animation: glowing 1300ms infinite;
|
||||
}
|
||||
@keyframes glowing {
|
||||
0% {
|
||||
box-shadow: 0 0 20px #a600ff;
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 40px #52057b;
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 20px #a600ff;
|
||||
}
|
||||
}
|
||||
.flash-button {
|
||||
animation: glowing 1300ms infinite;
|
||||
}
|
||||
|
||||
#case-details {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
{% endblock css %}
|
||||
@@ -148,6 +148,16 @@ urlpatterns = [
|
||||
views.collection_reset_answers,
|
||||
name="collection_reset_answers",
|
||||
),
|
||||
path(
|
||||
"collection/<int:exam_id>/reset_answers_user_list",
|
||||
views.collection_reset_answers_user_list,
|
||||
name="collection_reset_answers_user_list",
|
||||
),
|
||||
path(
|
||||
"collection/<int:exam_id>/<int:user_id>/reset_answers",
|
||||
views.collection_reset_answers_user,
|
||||
name="collection_reset_answers_user",
|
||||
),
|
||||
#path(
|
||||
# "question_schemas_preset",
|
||||
# views.question_schemas_preset,
|
||||
|
||||
+38
-1
@@ -1682,7 +1682,12 @@ def collection_take_start(request, pk):
|
||||
"""
|
||||
collection = get_object_or_404(CaseCollection, pk=pk)
|
||||
|
||||
valid_user = (collection.check_logged_in_user(request),)
|
||||
valid_user = collection.check_logged_in_user(request)
|
||||
|
||||
|
||||
# for now we only allow registered users....
|
||||
if not valid_user:
|
||||
raise PermissionDenied
|
||||
|
||||
cid_exam = None
|
||||
if collection.collection_type == "REV" or valid_user:
|
||||
@@ -2901,6 +2906,38 @@ def collection_question_schemas(request, exam_id: int):
|
||||
},
|
||||
)
|
||||
|
||||
def collection_reset_answers_user_list(request, exam_id: int):
|
||||
if request.htmx:
|
||||
collection = get_object_or_404(CaseCollection, pk=exam_id)
|
||||
cid_users = collection.cid_users.all()
|
||||
|
||||
if cid_users:
|
||||
return render(request, "atlas/collection_reset_answers_user_list.html", {"collection": collection, "cid_users": cid_users})
|
||||
else:
|
||||
return HttpResponse("No user answers.")
|
||||
|
||||
else:
|
||||
raise Http404("Invalid request")
|
||||
|
||||
def collection_reset_answers_user(request, exam_id: int, user_id: int):
|
||||
if request.htmx:
|
||||
collection = get_object_or_404(CaseCollection, pk=exam_id)
|
||||
|
||||
# Select all case details (answers are linked to these)
|
||||
case_details = collection.casedetail_set.all().prefetch_related()
|
||||
|
||||
# Delete all answers
|
||||
for case in case_details:
|
||||
user_answers = case.userreportanswer_set.filter(user_id=user_id)
|
||||
user_answers.delete()
|
||||
|
||||
collection.cid_users.filter(user_user_id=user_id).delete()
|
||||
collection.exam_user_status.filter(cid_user_exam__user_user_id=user_id).delete()
|
||||
|
||||
return HttpResponse("Success")
|
||||
|
||||
else:
|
||||
raise Http404("Invalid request")
|
||||
|
||||
def collection_reset_answers(request, exam_id: int):
|
||||
if request.htmx:
|
||||
|
||||
+4
-2
@@ -613,6 +613,8 @@ class ExamOrCollectionGenericBase(models.Model, AuthorMixin):
|
||||
default=False,
|
||||
)
|
||||
|
||||
exam_open_access = models.BooleanField(default=False, help_text="Set to true if you want any registered user to be able to take the exam.")
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
@@ -718,6 +720,8 @@ class ExamOrCollectionGenericBase(models.Model, AuthorMixin):
|
||||
return True
|
||||
|
||||
if cid is None and user_id is None:
|
||||
if user.is_anonymous:
|
||||
return False
|
||||
if user is not None:
|
||||
user_id = user.id
|
||||
else:
|
||||
@@ -869,8 +873,6 @@ class ExamBase(ExamOrCollectionGenericBase):
|
||||
default=False,
|
||||
)
|
||||
|
||||
exam_open_access = models.BooleanField(default=False, help_text="Set to true if you want any registered user to be able to take the exam.")
|
||||
|
||||
# randomise_question_order = models.BooleanField(
|
||||
# help_text="If an exam should randomise the order of questions in RTS.",
|
||||
# )
|
||||
|
||||
Reference in New Issue
Block a user