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