From 00323cc6bd89090d7393b54ed2982a2ddd7b3a43 Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 18 Nov 2024 10:44:27 +0000 Subject: [PATCH] improve case user answer management (and fix small bug) --- .../0064_casecollection_exam_open_access.py | 18 ++++++ atlas/templates/atlas/collection_detail.html | 8 +++ .../collection_reset_answers_user_list.html | 10 +++ atlas/templates/atlas/collection_viva.html | 64 +++++++++++-------- atlas/urls.py | 10 +++ atlas/views.py | 39 ++++++++++- generic/models.py | 6 +- 7 files changed, 125 insertions(+), 30 deletions(-) create mode 100644 atlas/migrations/0064_casecollection_exam_open_access.py create mode 100644 atlas/templates/atlas/collection_reset_answers_user_list.html diff --git a/atlas/migrations/0064_casecollection_exam_open_access.py b/atlas/migrations/0064_casecollection_exam_open_access.py new file mode 100644 index 00000000..413234a5 --- /dev/null +++ b/atlas/migrations/0064_casecollection_exam_open_access.py @@ -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.'), + ), + ] diff --git a/atlas/templates/atlas/collection_detail.html b/atlas/templates/atlas/collection_detail.html index af3d440f..8eb6b862 100644 --- a/atlas/templates/atlas/collection_detail.html +++ b/atlas/templates/atlas/collection_detail.html @@ -33,6 +33,7 @@

View as a viva collection here {% else %}

This collection will be available to view/take here (when active) +

Review collection here {% 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 + + +

{% endif %} diff --git a/atlas/templates/atlas/collection_reset_answers_user_list.html b/atlas/templates/atlas/collection_reset_answers_user_list.html new file mode 100644 index 00000000..6a12f6d9 --- /dev/null +++ b/atlas/templates/atlas/collection_reset_answers_user_list.html @@ -0,0 +1,10 @@ + +{% for cid_user_exam in cid_users %} + + +{% endfor %} + \ No newline at end of file diff --git a/atlas/templates/atlas/collection_viva.html b/atlas/templates/atlas/collection_viva.html index d30210f5..493dee72 100644 --- a/atlas/templates/atlas/collection_viva.html +++ b/atlas/templates/atlas/collection_viva.html @@ -58,12 +58,14 @@

Current Case

-
Waiting for case to load in linked window.
If you are seeing this message you probably need to open the viewer window and reload the case.
-
None
-
-
-
-
+
+
Waiting for case to load in linked window.
If you are seeing this message you probably need to open the viewer window and reload the case.
+
None
+
+
+
+
+
@@ -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("Case: "+c.data('title')); + $("#current-case-history").html("History: "+case_details['history']); + $("#current-case-discussion").html("Discussion: "+case_details['discussion']); + $("#current-case-report").html("Report: "+case_details['report']); console.log($(this).data('type')) if ($(this).data('type') == 'case') { - $('#current-case-series').text("Series: All"); + $('#current-case-series').html("Series: All"); } else { - $('#current-case-series').text("Series: " + $(this).data('series')); + $('#current-case-series').html("Series: " + $(this).data('series')); } bc.postMessage({"type": "open", "url" : url}); //if (win2 == false || win2.closed) { @@ -153,25 +155,33 @@ {% endblock %} {% block css %} - + {% endblock css %} \ No newline at end of file diff --git a/atlas/urls.py b/atlas/urls.py index 5a035463..cc2ed4af 100755 --- a/atlas/urls.py +++ b/atlas/urls.py @@ -148,6 +148,16 @@ urlpatterns = [ views.collection_reset_answers, name="collection_reset_answers", ), + path( + "collection//reset_answers_user_list", + views.collection_reset_answers_user_list, + name="collection_reset_answers_user_list", + ), + path( + "collection///reset_answers", + views.collection_reset_answers_user, + name="collection_reset_answers_user", + ), #path( # "question_schemas_preset", # views.question_schemas_preset, diff --git a/atlas/views.py b/atlas/views.py index 9fd6d003..5a61dc8a 100755 --- a/atlas/views.py +++ b/atlas/views.py @@ -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: diff --git a/generic/models.py b/generic/models.py index fd417534..fe990d3d 100644 --- a/generic/models.py +++ b/generic/models.py @@ -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.", # )