diff --git a/atlas/views.py b/atlas/views.py
index b6a36e6b..6d242259 100755
--- a/atlas/views.py
+++ b/atlas/views.py
@@ -1054,7 +1054,7 @@ def collection_detail_view(request, pk):
def collection_case_view(request, pk, case_number):
collection = get_object_or_404(CaseCollection, pk=pk)
- cases = collection.cases.all().prefetch_related()
+ cases = collection.cases.all().order_by("casedetail__sort_order").prefetch_related()
case = cases[case_number]
series_list = case.series.all().prefetch_related("images", "examination", "plane")
diff --git a/generic/models.py b/generic/models.py
index 95363aef..87dcf681 100644
--- a/generic/models.py
+++ b/generic/models.py
@@ -128,6 +128,10 @@ class ExamBase(models.Model):
class Meta:
abstract = True
+ def save(self, *args, recreate_json=True, **kwargs):
+ self.recreate_json = recreate_json
+ super().save(*args, **kwargs)
+
def get_exam_stats(self):
text = f"""{self.name}
{"-"*len(self.name)}
diff --git a/generic/templates/generic/exam_overview_headers.html b/generic/templates/generic/exam_overview_headers.html
index f7c298f7..69edd309 100644
--- a/generic/templates/generic/exam_overview_headers.html
+++ b/generic/templates/generic/exam_overview_headers.html
@@ -10,6 +10,14 @@
{% include 'exam_notes.html' %}
+{% if exam.recreate_json %}
+
+{% endif %}
+
This exam has {{question_number}} questions. Time limit: {{exam.time_limit}} seconds.
Exam mode: {{ exam.exam_mode }}
diff --git a/generic/views.py b/generic/views.py
index 358fd379..c8a04da7 100644
--- a/generic/views.py
+++ b/generic/views.py
@@ -1,5 +1,6 @@
from collections import defaultdict
import statistics
+import threading
from dal import autocomplete
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
@@ -425,7 +426,13 @@ class ExamViews(View, LoginRequiredMixin):
exam.recreate_json = True
exam.save()
- exam.get_exam_json()
+ # exam.get_exam_json()
+
+ # TODO: check if mememory leak?
+ t = threading.Thread(target=self.exam_json,
+ args=(request, pk))
+ t.setDaemon(True)
+ t.start()
return redirect("{}:exam_overview".format(self.app_name), pk=pk)
@@ -559,8 +566,11 @@ class ExamViews(View, LoginRequiredMixin):
request,
f"{self.app_name}/base.html",
{
- "simple_content": format_html("""Answer scores updated
- Return""", reverse(f"{self.app_name}:exam_scores_cid", kwargs={"pk": exam.pk}))
+ "simple_content": format_html(
+ """Answer scores updated
+ Return""",
+ reverse(f"{self.app_name}:exam_scores_cid", kwargs={"pk": exam.pk}),
+ )
},
)
@@ -746,9 +756,7 @@ class ExamViews(View, LoginRequiredMixin):
question_unmarked_map = []
for q in questions:
count = int(q.get_unmarked_user_answer_count(exam_pk=exam.pk))
- question_unmarked_map.append(
- (q, count, count)
- )
+ question_unmarked_map.append((q, count, count))
return render(
request,
@@ -955,7 +963,7 @@ class ExamViews(View, LoginRequiredMixin):
exam.recreate_json = False
exam.json_creation_time = time
- exam.save()
+ exam.save(recreate_json=False)
# We also try to clear the cache of any associated questions (longs)
# see exam_question_json
@@ -1304,6 +1312,7 @@ class ExaminationAutocomplete(autocomplete.Select2QuerySetView):
return qs
+
class CidUserExamView(CidManagerRequiredMixin, SingleTableMixin, FilterView):
model = CidUser
table_class = CidUserExamTable
@@ -1336,6 +1345,7 @@ class CidUserExamView(CidManagerRequiredMixin, SingleTableMixin, FilterView):
context["exams"] = True
return context
+
class CidUserView(CidManagerRequiredMixin, SingleTableMixin, FilterView):
model = CidUser
table_class = CidUserTable
@@ -1385,6 +1395,7 @@ def group_view(request):
{"groups": groups},
)
+
@user_is_cid_user_manager
def group_view(request):
groups = CidUserGroup.objects.filter(archive=False)
@@ -1395,6 +1406,7 @@ def group_view(request):
{"groups": groups, "view_all": False},
)
+
@user_is_cid_user_manager
def group_view_all(request):
groups = CidUserGroup.objects.filter()
@@ -1411,6 +1423,7 @@ def group_view_all(request):
def group_email_resend(request, pk):
return group_email(request, pk, resend=True)
+
@login_required
@user_is_cid_user_manager
def group_email_results_resend(request, pk):
@@ -1430,24 +1443,24 @@ def group_email(request, pk, resend=False):
return render(
request,
"generic/group_emailed.html",
- #{"sent": sent, "not_sent": not_sent, "users_count": users.count()},
+ # {"sent": sent, "not_sent": not_sent, "users_count": users.count()},
{"users": users, "users_count": users.count()},
)
- #sent = []
- #not_sent = []
- #for u in users:
+ # sent = []
+ # not_sent = []
+ # for u in users:
# success, msg = u.email_details(resend=resend)
# if success:
# sent.append(u)
# else:
# not_sent.append((u, msg))
- #return render(
+ # return render(
# request,
# "generic/group_emailed.html",
# {"sent": sent, "not_sent": not_sent, "users_count": users.count()},
- #)
+ # )
@user_is_cid_user_manager
@@ -1457,11 +1470,13 @@ def group_email_results(request, pk, resend=False):
if resend:
users = group.ciduser_set.filter(active=True, internal_candidate=True)
else:
- users = group.ciduser_set.filter(active=True, internal_candidate=True, results_email_sent=False)
+ users = group.ciduser_set.filter(
+ active=True, internal_candidate=True, results_email_sent=False
+ )
- #sent = []
- #not_sent = []
- #for u in users:
+ # sent = []
+ # not_sent = []
+ # for u in users:
# success, msg = u.email_results(resend=resend)
# if success:
# sent.append(u)
@@ -1471,18 +1486,22 @@ def group_email_results(request, pk, resend=False):
return render(
request,
"generic/group_emailed.html",
- #{"sent": sent, "not_sent": not_sent, "users_count": users.count()},
+ # {"sent": sent, "not_sent": not_sent, "users_count": users.count()},
{"users": users, "users_count": users.count()},
)
+
@user_is_cid_user_manager
def candidate_email_results(request, cid, resend=False):
user = CidUser.objects.get(cid=cid)
- email_sent, comment = user.email_results(additional_emails=["priya.suresh@nhs.net"], resend=True)
+ email_sent, comment = user.email_results(
+ additional_emails=["priya.suresh@nhs.net"], resend=True
+ )
return JsonResponse({"sent": email_sent, "comment": comment})
+
@user_is_cid_user_manager
def candidate_email_results_resend(request, cid, resend=True):
return candidate_email_results(request, cid, resend=True)
@@ -1637,14 +1656,17 @@ class CidUserCreate(RevisionMixin, CidManagerRequiredMixin, CreateView):
model = CidUser
form_class = CidUserForm
+
class CidUserUpdate(RevisionMixin, CidManagerRequiredMixin, UpdateView):
model = CidUser
form_class = CidUserForm
+
class CidUserGroupCreate(RevisionMixin, CidManagerRequiredMixin, CreateView):
model = CidUserGroup
form_class = CidUserGroupForm
+
class CidUserGroupUpdate(RevisionMixin, CidManagerRequiredMixin, UpdateView):
model = CidUserGroup
form_class = CidUserGroupForm