From 65b1d2da3c97fd148510a1edb95bd4cd61284e34 Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 28 Nov 2022 15:48:50 +0000 Subject: [PATCH] Further candidate management improvements --- anatomy/forms.py | 3 +- anatomy/static/css/anatomy.css | 4 ++ generic/forms.py | 17 ++++++ generic/models.py | 56 +++++++++++++++---- generic/templates/generic/ciduser_form.html | 51 ++++++++++------- .../templates/generic/user_group_view.html | 2 +- .../generic/user_group_view_detail.html | 43 ++++++++++++++ generic/urls.py | 1 + generic/views.py | 21 +++++++ templates/privacy.html | 48 +++++++++------- templates/profile.html | 32 ++++++++--- 11 files changed, 219 insertions(+), 59 deletions(-) create mode 100755 generic/templates/generic/user_group_view_detail.html diff --git a/anatomy/forms.py b/anatomy/forms.py index fc4540a2..8bc274e2 100644 --- a/anatomy/forms.py +++ b/anatomy/forms.py @@ -22,7 +22,7 @@ from .models import ( QuestionType, Exam, ) -from generic.models import Examination +from generic.models import CidUserGroup, Examination from django.contrib.admin.widgets import FilteredSelectMultiple from django.forms.widgets import RadioSelect, TextInput, Textarea @@ -204,6 +204,7 @@ class BodyPartForm(ModelForm): class ExamForm(ExamFormMixin, ModelForm): + class Meta(ExamFormMixin.Meta): model = Exam diff --git a/anatomy/static/css/anatomy.css b/anatomy/static/css/anatomy.css index 80e5ef6d..d2eeec72 100644 --- a/anatomy/static/css/anatomy.css +++ b/anatomy/static/css/anatomy.css @@ -907,4 +907,8 @@ tr:has(.errorlist){ form .submit-button { margin-top: 10px; margin-bottom: 10px; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 10px; } \ No newline at end of file diff --git a/generic/forms.py b/generic/forms.py index 2404c47a..dddcd9f7 100755 --- a/generic/forms.py +++ b/generic/forms.py @@ -60,6 +60,23 @@ from sbas.models import Question as SbasQuestion class ExamFormMixin: + def __init__(self, *args, user, **kwargs) -> None: + super(ModelForm, self).__init__(*args, **kwargs) + + if user.is_superuser or user.groups.filter(name="cid_manager").exists(): + cid_user_group_queryset = CidUserGroup.objects.all() + user_user_group_queryset = UserUserGroup.objects.all() + else: + cid_user_group_queryset = CidUserGroup.objects.none() + user_user_group_queryset = UserUserGroup.objects.none() + self.fields["cid_user_groups"] = ModelMultipleChoiceField( + required=False, + queryset=cid_user_group_queryset, + ) + self.fields["user_user_groups"] = ModelMultipleChoiceField( + required=False, + queryset=user_user_group_queryset, + ) class Meta: fields = [ "name", diff --git a/generic/models.py b/generic/models.py index d2f2759e..1dd88985 100644 --- a/generic/models.py +++ b/generic/models.py @@ -422,16 +422,16 @@ class QuestionNote(models.Model): def get_short_str(self): return f"{self.note_type} - {self.note}" +EXAM_TYPES = ( + ("Physics", "physics_exams"), + ("Rapids", "rapid_exams"), + ("SBAs", "sba_exams"), + ("Anatomy", "anatomy_exams"), + ("Longs", "longs_exams"), + ("CaseCollection", "casecollection_exams"), +) class CidUser(models.Model): - EXAM_TYPES = ( - ("Physics", "physics_exams"), - ("Rapids", "rapid_exams"), - ("SBAs", "sba_exams"), - ("Anatomy", "anatomy_exams"), - ("Longs", "longs_exams"), - ("CaseCollection", "casecollection_exams"), - ) cid = models.IntegerField(blank=True, null=True, unique=True) passcode = models.CharField(blank=True, max_length=50) @@ -463,13 +463,13 @@ class CidUser(models.Model): def get_cid_exams(self): available_exams = [] - for n, t in self.EXAM_TYPES: + for n, t in EXAM_TYPES: exam_rel = getattr(self, t) if exam_rel.exists(): exams = exam_rel.filter(exam_mode=True, archive=False).order_by("name") available_exams.append((n, exams)) - return available_exams + return dict(available_exams) def generate_exam_report(self): exam_list = self.get_cid_exams() @@ -655,6 +655,13 @@ class CidUserGroup(models.Model): return reverse("generic:cid_group_update", kwargs={"pk": self.pk}) +USER_GROUP_EXAMS = ( + ("SBAs", "sba_user_user_groups"), + ("Physics", "physics_user_user_groups"), + ("Anatomy", "anatomy_user_user_groups"), + ("Rapids", "rapid_user_user_groups"), + ("Longs", "longs_user_user_groups"), +) class UserUserGroup(models.Model): name = models.CharField(blank=True, max_length=50, help_text="Name of the User Group") @@ -675,6 +682,15 @@ class UserUserGroup(models.Model): s = ", ".join([f"{user.id} - {user.username} ({user.email})" for user in users]) return s + def GetGroupExams(self): + exams = defaultdict(list) + for t, rel in USER_GROUP_EXAMS: + exam_rel = getattr(self, rel) + if exam_rel.exists(): + exams[t].extend(exam_rel.all()) + + return dict(exams) + def get_absolute_url(self): return reverse("generic:user_group_update", kwargs={"pk": self.pk}) @@ -684,6 +700,15 @@ class UserGrades(models.Model): def __str__(self): return self.name +USER_EXAM_TYPES = ( + ("Physics", "user_physics_exams"), + ("Rapids", "user_rapid_exams"), + ("SBAs", "user_sba_exams"), + ("Anatomy", "user_anatomy_exams"), + ("Longs", "user_longs_exams"), + #("CaseCollection", "user_casecollection_exams"), +) + class UserProfile(models.Model): user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) supervisor = models.ForeignKey("Supervisor", on_delete=models.SET_NULL, blank=True, null=True, related_name="trainee") @@ -700,6 +725,17 @@ class UserProfile(models.Model): username = property(getusername) + def get_exams(self): + available_exams = defaultdict(list) + + for n, t in USER_EXAM_TYPES: + exam_rel = getattr(self.user, t) + if exam_rel.exists(): + exams = exam_rel.filter(exam_mode=True, archive=False).order_by("name") + available_exams[n].extend(exams) + + return dict(available_exams) + class Supervisor(models.Model): """Model to hold individual supervisor details (email and name) diff --git a/generic/templates/generic/ciduser_form.html b/generic/templates/generic/ciduser_form.html index b41fd6f7..088e5ec8 100755 --- a/generic/templates/generic/ciduser_form.html +++ b/generic/templates/generic/ciduser_form.html @@ -6,33 +6,46 @@ {% block css %} {% endblock %} {% block js %} - -{{form.media}} + + {{form.media}} - + - + {% endblock %} {% block content %} -

Edit CID User / {{ciduser.cid}}

-Use this form to edit a CID user. -
- {% csrf_token %} +

Edit CID User / {{ciduser.cid}}

+ Use this form to edit a CID user. + + {% csrf_token %} {{ form|crispy }} - -
+ + -

Exams

-

The user is currently part of the following exams

+

Exams

+

The user is currently part of the following exams

-

-{{ object.get_cid_exams }} -

+

+ {% with object.get_cid_exams as exam_map %} + {% for exam_type, exams in exam_map.items %} +

{{exam_type}}

+ + {% empty %} + No exams. + {% endfor %} + {% endwith %} +

-

-These should be edited via the exam candidate page. If you need to manually toggle you can do so here (you shouldn't) -

+

+ These should be edited via the exam candidate page. If you need to manually toggle you can do so here (you shouldn't) +

{% endblock %} \ No newline at end of file diff --git a/generic/templates/generic/user_group_view.html b/generic/templates/generic/user_group_view.html index 0d24c303..d2a0915d 100755 --- a/generic/templates/generic/user_group_view.html +++ b/generic/templates/generic/user_group_view.html @@ -6,7 +6,7 @@ Create new group

{% for group in groups %} -

{{group.name}} +

{{group.name}}

{% comment %}