Compare commits
4
Commits
cf9b514597
...
80412dcbe0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80412dcbe0 | ||
|
|
a024d7fca7 | ||
|
|
33b49c9430 | ||
|
|
4f60440ea1 |
@@ -1,4 +1,4 @@
|
||||
{% extends 'anatomy/base.html' %}
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="question-display-block">
|
||||
|
||||
+45
-29
@@ -68,6 +68,9 @@ from django.forms.utils import from_current_timezone, to_current_timezone
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import Submit
|
||||
|
||||
from dal import autocomplete
|
||||
|
||||
|
||||
class SplitDateTimeFieldDefaultTime(SplitDateTimeField):
|
||||
def compress(self, data_list):
|
||||
if data_list:
|
||||
@@ -79,9 +82,9 @@ class SplitDateTimeFieldDefaultTime(SplitDateTimeField):
|
||||
)
|
||||
if data_list[1] in self.empty_values:
|
||||
data_list[1] = datetime.time(0, 1)
|
||||
#raise ValidationError(
|
||||
# raise ValidationError(
|
||||
# self.error_messages["invalid_time"], code="invalid_time"
|
||||
#)
|
||||
# )
|
||||
result = datetime.datetime.combine(*data_list)
|
||||
return from_current_timezone(result)
|
||||
return None
|
||||
@@ -98,9 +101,9 @@ class SplitDateTimeFieldDefaultTimeEnd(SplitDateTimeField):
|
||||
)
|
||||
if data_list[1] in self.empty_values:
|
||||
data_list[1] = datetime.time(23, 59)
|
||||
#raise ValidationError(
|
||||
# raise ValidationError(
|
||||
# self.error_messages["invalid_time"], code="invalid_time"
|
||||
#)
|
||||
# )
|
||||
result = datetime.datetime.combine(*data_list)
|
||||
return from_current_timezone(result)
|
||||
return None
|
||||
@@ -111,29 +114,28 @@ class ExamFormMixin:
|
||||
super(ModelForm, self).__init__(*args, **kwargs)
|
||||
|
||||
self.helper = FormHelper()
|
||||
self.helper.form_id = 'id-exam-form'
|
||||
self.helper.form_class = 'exam-form'
|
||||
self.helper.form_method = 'post'
|
||||
self.helper.form_action = 'submit'
|
||||
self.helper.form_id = "id-exam-form"
|
||||
self.helper.form_class = "exam-form"
|
||||
self.helper.form_method = "post"
|
||||
self.helper.form_action = "submit"
|
||||
|
||||
self.helper.add_input(Submit("submit", "Submit"))
|
||||
|
||||
self.helper.add_input(Submit('submit', 'Submit'))
|
||||
|
||||
#if user.is_superuser or user.groups.filter(name="cid_user_manager").exists():
|
||||
# if user.is_superuser or user.groups.filter(name="cid_user_manager").exists():
|
||||
# cid_user_group_queryset = CidUserGroup.objects.filter(archive=False)
|
||||
# user_user_group_queryset = UserUserGroup.objects.filter(archive=False)
|
||||
#else:
|
||||
# else:
|
||||
# cid_user_group_queryset = CidUserGroup.objects.none()
|
||||
# user_user_group_queryset = UserUserGroup.objects.none()
|
||||
|
||||
#self.fields["cid_user_groups"] = ModelMultipleChoiceField(
|
||||
# self.fields["cid_user_groups"] = ModelMultipleChoiceField(
|
||||
# required=False,
|
||||
# queryset=cid_user_group_queryset,
|
||||
#)
|
||||
#self.fields["user_user_groups"] = ModelMultipleChoiceField(
|
||||
# )
|
||||
# self.fields["user_user_groups"] = ModelMultipleChoiceField(
|
||||
# required=False,
|
||||
# queryset=user_user_group_queryset,
|
||||
#)
|
||||
# )
|
||||
self.fields["start_date"] = SplitDateTimeFieldDefaultTime(
|
||||
widget=SplitDateTimeWidget(
|
||||
date_attrs={"type": "date", "class": "datepicker"},
|
||||
@@ -169,8 +171,8 @@ class ExamFormMixin:
|
||||
"active",
|
||||
"publish_results",
|
||||
"archive",
|
||||
#"cid_user_groups",
|
||||
#"user_user_groups",
|
||||
# "cid_user_groups",
|
||||
# "user_user_groups",
|
||||
# "author",
|
||||
]
|
||||
|
||||
@@ -199,6 +201,7 @@ class ExamAuthorFormMixin(ModelForm):
|
||||
widget=FilteredSelectMultiple(verbose_name="Authors", is_stacked=False),
|
||||
)
|
||||
|
||||
|
||||
class ExamMarkerFormMixin(ModelForm):
|
||||
class Meta:
|
||||
fields = ["markers"]
|
||||
@@ -214,7 +217,7 @@ class ExamMarkerFormMixin(ModelForm):
|
||||
|
||||
class ExamGroupsFormMixin(ModelForm):
|
||||
class Meta:
|
||||
#model = ExamCollection
|
||||
# model = ExamCollection
|
||||
fields = ("cid_user_groups", "user_user_groups")
|
||||
|
||||
def __init__(self, *args, user, **kwargs) -> None:
|
||||
@@ -227,10 +230,14 @@ class ExamGroupsFormMixin(ModelForm):
|
||||
cid_user_group_queryset = CidUserGroup.objects.filter(archive=False)
|
||||
user_user_group_queryset = UserUserGroup.objects.filter(archive=False)
|
||||
else:
|
||||
cid_user_group_queryset = CidUserGroup.objects.filter(archive=False, open_access=True)
|
||||
user_user_group_queryset = UserUserGroup.objects.none(archive=False, open_access=True)
|
||||
#cid_user_group_queryset = CidUserGroup.objects.none()
|
||||
#user_user_group_queryset = UserUserGroup.objects.none()
|
||||
cid_user_group_queryset = CidUserGroup.objects.filter(
|
||||
archive=False, open_access=True
|
||||
)
|
||||
user_user_group_queryset = UserUserGroup.objects.none(
|
||||
archive=False, open_access=True
|
||||
)
|
||||
# cid_user_group_queryset = CidUserGroup.objects.none()
|
||||
# user_user_group_queryset = UserUserGroup.objects.none()
|
||||
|
||||
self.fields["cid_user_groups"] = ModelMultipleChoiceField(
|
||||
required=False,
|
||||
@@ -667,13 +674,23 @@ class UserUserForm(Form):
|
||||
first_name = CharField(max_length=255, required=True)
|
||||
last_name = CharField(max_length=255, required=True)
|
||||
grade = ModelChoiceField(UserGrades.objects.all(), required=False)
|
||||
|
||||
class TraineeForm(Form):
|
||||
username = EmailField(
|
||||
required=True,
|
||||
help_text="Username / email should be the same. Ideally this should be an nhs email.",
|
||||
)
|
||||
first_name = CharField(max_length=255, required=True)
|
||||
last_name = CharField(max_length=255, required=True)
|
||||
grade = ModelChoiceField(UserGrades.objects.all(), required=False)
|
||||
supervisor = ModelChoiceField(
|
||||
Supervisor.objects.all(), required=False
|
||||
Supervisor.objects.all(), required=False, widget=autocomplete.ModelSelect2(url='generic:supervisor-autocomplete')
|
||||
) # Needs to be a user/object ref
|
||||
#
|
||||
# class Meta:
|
||||
#
|
||||
# fields = ("username", "first_name", "last_name")
|
||||
|
||||
#class Meta:
|
||||
# widgets = {
|
||||
# "supervisor" : autocomplete.ModelSelect2(url='generic:supervisor-autocomplete')
|
||||
# }
|
||||
|
||||
|
||||
class SupervisorForm(ModelForm):
|
||||
@@ -751,4 +768,3 @@ class ExamCollectionCloneForm(ModelForm):
|
||||
class Meta:
|
||||
model = ExamCollection
|
||||
fields = ("name", "date")
|
||||
|
||||
|
||||
@@ -39,44 +39,67 @@
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<h3>Exams</h3>
|
||||
The group is currently associated with the following exams.
|
||||
The group is currently associated with the following exams. This allows the users within the group to be easily added to the exam. It will not automatically give members of the group access to the exam.
|
||||
{% if group_type == "cid" %}
|
||||
Add more <a href='{% url "generic:cid_group_exams" group.pk %}'>here</a>.
|
||||
{% else %}
|
||||
Add more <a href='{% url "generic:user_group_exams" group.pk %}'>here</a>.
|
||||
{% endif %}
|
||||
<p>It is possible to quickly add or remove all group candidates from an exam by clicking the buttons below. This will only affect the <b>{{users|length}}</b> candidates in this group. You will need to refresh the page to see updated candidate counts.</p>
|
||||
{% with group.GetGroupExams as exam_map %}
|
||||
{% for key, value in exam_map.items %}
|
||||
<h4>{{key}}</h4>
|
||||
<ul>
|
||||
<div>
|
||||
{% for exam in value %}
|
||||
<li>
|
||||
<a href="{{exam.get_absolute_url}}">{{exam}}</a>
|
||||
<div class="d-flex">
|
||||
<a href="{{exam.get_absolute_url}}" class="px-2">{{exam}}</a>
|
||||
{% if group_type == "cid" %}
|
||||
<a href="{{exam.get_cid_edit_url}}" class="edit-link">Edit candidates</a>
|
||||
<a href="{{exam.get_cid_edit_url}}" class="edit-link" px-2>Edit candidates</a>
|
||||
{% comment %} <button>Add group candidates</button>
|
||||
<button>Remove group candidates</button> {% endcomment %}
|
||||
{% else %}
|
||||
<a href="{{exam.get_user_edit_url}}" class="edit-link">Edit candidates</a>
|
||||
<a href="{{exam.get_user_edit_url}}" class="edit-link px-2">Edit candidates</a>
|
||||
<form>
|
||||
<input type="hidden" name="exam_id" value="{{exam.pk}}">
|
||||
<input type="hidden" name="exam_type" value="{{exam.app_name}}">
|
||||
<button
|
||||
class="btn btn-sm px-2"
|
||||
hx-post="{% url 'generic:user_group_add_candidates_to_exams' group.pk %}"
|
||||
title="Add all group candidates to this exam"
|
||||
name="action"
|
||||
value="add"
|
||||
>Add group candidates</button>
|
||||
<button
|
||||
hx-post="{% url 'generic:user_group_add_candidates_to_exams' group.pk %}"
|
||||
title="Remove all group candidates to this exam"
|
||||
class="btn btn-sm px-2"
|
||||
name="action"
|
||||
value="remove"
|
||||
>Remove group candidates</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
<span class="cid-number">
|
||||
|
||||
|
||||
<div class="px-2 ms-auto ">
|
||||
{% if group_type == "cid" %}
|
||||
(Cid candidate count: {{exam.valid_cid_users.count}})
|
||||
{% else %}
|
||||
(User candidate count: {{exam.valid_user_users.count}})
|
||||
{% endif %}
|
||||
</span>
|
||||
</li>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<style>
|
||||
td, th { padding-left: 10px }
|
||||
|
||||
.cid-number {float: right}
|
||||
|
||||
.edit-link {
|
||||
font-size: smaller;
|
||||
opacity: 60%;
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
{% extends "generic/base.html" %}
|
||||
<!-- {% load static from static %} -->
|
||||
|
||||
{% load crispy_forms_tags %}
|
||||
{% block css %}
|
||||
{% endblock %}
|
||||
{% block js %}
|
||||
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
|
||||
{{form.media}}
|
||||
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
|
||||
<!-- {{ form.media }} -->
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<h2>Create Trainee</h2>
|
||||
Use this form to create a user. Only existing supervisors can be added (<a href="{% url 'generic:supervisor_create' %}">create them first</a> and refresh this page or add them later if they do not exist).
|
||||
{% if errors %}
|
||||
<div class="alert alert-info" role="alert">{{errors}}</a></div>
|
||||
{% endif %}
|
||||
<form action="" method="post" enctype="multipart/form-data" id="condition-form">
|
||||
{% csrf_token %}
|
||||
|
||||
<table>
|
||||
{{ form|crispy }}
|
||||
</table>
|
||||
<input type="submit" class="submit-button" value="Submit" name="submit">
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -9,6 +9,7 @@
|
||||
{% for i in "123456"|make_list %}
|
||||
<a href='{% url "trainees_grade" "ST"|add:i %}'>ST{{i}}</a>{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
(<a href="{% url 'create_trainee' %}" title="Click to add a trainee to the platform, creating an account for them.">Add trainee</a>)
|
||||
|
||||
<h2>
|
||||
{% if grade %}
|
||||
@@ -38,7 +39,12 @@
|
||||
<a href="{% url 'account_profile_update' trainee.user.username %}" class="add-supervisor">add</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><a href="{% url 'account_update' trainee.user.username %}">User</a>/<a href="{% url 'account_profile_update' trainee.user.username %}">Profile</a></td>
|
||||
<td><a href="{% url 'account_update' trainee.user.username %}">User</a>/<a href="{% url 'account_profile_update' trainee.user.username %}">Profile</a>
|
||||
<span class="hover-highlight"><i class="bi bi-x-circle" title="Click to remove trainee status"
|
||||
hx-get = "{% url 'generic:user_not_trainee' trainee.user.pk %}"
|
||||
></i></span>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{% extends "generic/base.html" %}
|
||||
<!-- {% load static from static %} -->
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block css %}
|
||||
{% endblock %}
|
||||
@@ -13,8 +14,8 @@
|
||||
<!-- {{ form.media }} -->
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<h2>Edit User / {{ciduser.cid}}</h2>
|
||||
Use this form to create a user. Only existing supervisors can be added (<a href="{% url 'generic:supervisor_create' %}">create them first</a> and refresh this page or add them later if they do not exist).
|
||||
<h2>Create User</h2>
|
||||
Use this form to create a user. Create a trainee <a href="{% url 'create_trainee' %}">here</a>.
|
||||
{% if errors %}
|
||||
<div class="alert alert-info" role="alert">{{errors}}</a></div>
|
||||
{% endif %}
|
||||
@@ -22,7 +23,7 @@ Use this form to create a user. Only existing supervisors can be added (<a href=
|
||||
{% csrf_token %}
|
||||
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
{{ form|crispy }}
|
||||
</table>
|
||||
<input type="submit" class="submit-button" value="Submit" name="submit">
|
||||
</form>
|
||||
|
||||
+23
-1
@@ -1,6 +1,6 @@
|
||||
from django.urls import path, include
|
||||
|
||||
from generic.models import Examination
|
||||
from generic.models import Examination, Supervisor
|
||||
from . import views
|
||||
from generic.views import ExamViews as GenericExamViews, GenericViewBase
|
||||
|
||||
@@ -42,6 +42,13 @@ urlpatterns = [
|
||||
),
|
||||
name="examination-autocomplete",
|
||||
),
|
||||
path(
|
||||
"supervisor-autocomplete",
|
||||
views.SupervisorAutocomplete.as_view(
|
||||
model=Supervisor
|
||||
),
|
||||
name="supervisor-autocomplete",
|
||||
),
|
||||
path(
|
||||
"cids/manage/<int:pk>/update", views.CidUserUpdate.as_view(), name="update_cid"
|
||||
),
|
||||
@@ -113,6 +120,11 @@ urlpatterns = [
|
||||
views.users_bulk_edit,
|
||||
name="users_bulk_edit",
|
||||
),
|
||||
path(
|
||||
"user/<int:user_id>/not_trainee",
|
||||
views.user_not_trainee,
|
||||
name="user_not_trainee",
|
||||
),
|
||||
path("user/group/", views.user_group_view, name="user_group_view"),
|
||||
path("user/group/all", views.user_group_view_all, name="user_group_view_all"),
|
||||
path(
|
||||
@@ -120,6 +132,16 @@ urlpatterns = [
|
||||
views.user_group_view_detail,
|
||||
name="user_group_detail",
|
||||
),
|
||||
path(
|
||||
"user/group/<int:group_id>/add",
|
||||
views.user_group_add_candidates_to_exams,
|
||||
name="user_group_add_candidates_to_exams",
|
||||
),
|
||||
path(
|
||||
"user/group/<int:group_id>/",
|
||||
views.user_group_view_detail,
|
||||
name="user_group_detail",
|
||||
),
|
||||
path(
|
||||
"user/group/<int:pk>/exams",
|
||||
views.UserGroupExamUpdate.as_view(),
|
||||
|
||||
+83
-7
@@ -53,7 +53,7 @@ from generic.mixins import CheckCanEditMixin, SuperuserRequiredMixin
|
||||
|
||||
import zipfile
|
||||
from django.core.files.base import ContentFile
|
||||
|
||||
from django.db.models import Q
|
||||
|
||||
from .forms import (
|
||||
CidGroupExamForm,
|
||||
@@ -65,6 +65,7 @@ from .forms import (
|
||||
CidUserGroupForm,
|
||||
ExaminationMergeForm,
|
||||
SupervisorForm,
|
||||
TraineeForm,
|
||||
UserGroupExamForm,
|
||||
CidGroupExamForm,
|
||||
UserUserForm,
|
||||
@@ -133,6 +134,17 @@ class CidManagerRequiredMixin(UserPassesTestMixin):
|
||||
# return obj
|
||||
# raise PermissionDenied() # or Http404
|
||||
|
||||
def get_exam_model_from_app_name(app_name: str) -> ExamBase:
|
||||
EXAM_MAP = {
|
||||
"physics": PhysicsExam,
|
||||
"anatomy": AnatomyExam,
|
||||
"rapids": RapidsExam,
|
||||
"longs": LongsExam,
|
||||
"sbas": SbasExam,
|
||||
}
|
||||
|
||||
return EXAM_MAP[app_name]
|
||||
|
||||
|
||||
def normaliseRapidsScore(score):
|
||||
if score == 49:
|
||||
@@ -2597,6 +2609,23 @@ class ExaminationAutocomplete(autocomplete.Select2QuerySetView):
|
||||
return Examination.objects.none()
|
||||
|
||||
return qs
|
||||
class SupervisorAutocomplete(autocomplete.Select2QuerySetView):
|
||||
def get_queryset(self):
|
||||
# TODO: we should probably filter this to only
|
||||
# allow access by trainees / other suprevisors
|
||||
if not self.request.user.is_authenticated:
|
||||
return Supervisor.objects.none()
|
||||
|
||||
qs = Supervisor.objects.all()
|
||||
|
||||
if self.q:
|
||||
# This raises a fielderror which breaks creating a new item if not caught
|
||||
try:
|
||||
qs = qs.filter(Q(email__icontains=self.q) | Q(name__icontains=self.q))
|
||||
except FieldError:
|
||||
return Supervisor.objects.none()
|
||||
|
||||
return qs
|
||||
|
||||
|
||||
class CidUserExamView(CidManagerRequiredMixin, SingleTableMixin, FilterView):
|
||||
@@ -2709,6 +2738,30 @@ def cid_group_view_all(request):
|
||||
{"groups": groups, "view_all": True},
|
||||
)
|
||||
|
||||
@user_is_cid_user_manager
|
||||
def user_group_add_candidates_to_exams(request, group_id):
|
||||
if request.htmx:
|
||||
group = get_object_or_404(UserUserGroup, pk=group_id)
|
||||
|
||||
exam_id = request.POST.get("exam_id")
|
||||
exam_type = request.POST.get("exam_type")
|
||||
|
||||
ExamModel = get_exam_model_from_app_name(exam_type)
|
||||
|
||||
exam = get_object_or_404(ExamModel, pk=exam_id)
|
||||
|
||||
if request.POST.get("action") == "remove":
|
||||
exam.valid_user_users.remove(*group.users.all())
|
||||
return HttpResponse(f"Candidates removed")
|
||||
else:
|
||||
exam.valid_user_users.add(*group.users.all())
|
||||
return HttpResponse(f"Candidates added")
|
||||
#exam.save()
|
||||
|
||||
|
||||
|
||||
raise PermissionDenied() # or Http404
|
||||
pass
|
||||
|
||||
@user_is_cid_user_manager
|
||||
def user_group_view_detail(request, group_id):
|
||||
@@ -2756,6 +2809,14 @@ def get_user_selection_from_request(request):
|
||||
user_models = User.objects.filter(id__in=selected_users)
|
||||
return user_models
|
||||
|
||||
@user_is_cid_user_manager
|
||||
def user_not_trainee(request, user_id):
|
||||
user = get_object_or_404(User, pk=user_id)
|
||||
|
||||
user.userprofile.peninsula_trainee = False
|
||||
user.userprofile.save()
|
||||
|
||||
return HttpResponse(f"{user.username} is no longer a trainee", content_type="text/plain")
|
||||
|
||||
@user_is_cid_user_manager
|
||||
def users_bulk_edit(request):
|
||||
@@ -3321,12 +3382,24 @@ def trainees(request, grade: None|str=None):
|
||||
|
||||
return render(request, "generic/trainees.html", context)
|
||||
|
||||
def create_user(request, context=None):
|
||||
def create_trainee(request, context=None):
|
||||
return create_user(request, context, trainee=True)
|
||||
|
||||
@user_is_cid_user_manager
|
||||
def create_user(request, context=None, trainee: bool=False):
|
||||
if trainee:
|
||||
form_template = "generic/trainee_creation_form.html"
|
||||
else:
|
||||
form_template = "generic/user_creation_form.html"
|
||||
# if this is a POST request we need to process the form data
|
||||
if request.method == "POST":
|
||||
# create a form instance and populate it with data from the request:
|
||||
if trainee:
|
||||
form = TraineeForm(request.POST)
|
||||
else:
|
||||
form = UserUserForm(request.POST)
|
||||
# check whether it's valid:
|
||||
|
||||
if form.is_valid():
|
||||
try:
|
||||
user_dict = {
|
||||
@@ -3342,19 +3415,19 @@ def create_user(request, context=None):
|
||||
errors = f"Unable to create account: {error}"
|
||||
return render(
|
||||
request,
|
||||
"generic/user_creation_form.html",
|
||||
form_template,
|
||||
{"form": form, "errors": errors},
|
||||
)
|
||||
|
||||
try:
|
||||
user_profile = UserProfile.objects.get(user=new_user)
|
||||
user_profile.peninsula_trainee = True
|
||||
user_profile.peninsula_trainee = trainee
|
||||
|
||||
if request.POST["grade"]:
|
||||
grade = UserGrades.objects.get(pk=request.POST["grade"])
|
||||
user_profile.grade = grade
|
||||
|
||||
if request.POST["supervisor"]:
|
||||
if "supervisor" in request.POST and request.POST["supervisor"]:
|
||||
supervisor = Supervisor.objects.get(pk=request.POST["supervisor"])
|
||||
user_profile.supervisor = supervisor
|
||||
|
||||
@@ -3364,7 +3437,7 @@ def create_user(request, context=None):
|
||||
errors = f"Unable to create account profile {error}"
|
||||
return render(
|
||||
request,
|
||||
"generic/user_creation_form.html",
|
||||
form_template,
|
||||
{"form": form, "errors": errors},
|
||||
)
|
||||
|
||||
@@ -3372,10 +3445,13 @@ def create_user(request, context=None):
|
||||
return reverse_lazy("accounts_list")
|
||||
|
||||
# if a GET (or any other method) we'll create a blank form
|
||||
else:
|
||||
if trainee:
|
||||
form = TraineeForm()
|
||||
else:
|
||||
form = UserUserForm()
|
||||
|
||||
return render(request, "generic/user_creation_form.html", {"form": form})
|
||||
return render(request, form_template, {"form": form})
|
||||
|
||||
|
||||
class SupervisorDetail(CidManagerRequiredMixin, DetailView):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends 'longs/base.html' %}
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="question-display-block">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends 'physics/base.html' %}
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="physics">
|
||||
|
||||
@@ -1275,3 +1275,11 @@ tr:has(> td > a) {
|
||||
color: lightgray;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.hover-highlight {
|
||||
opacity: 50%;
|
||||
}
|
||||
.hover-highlight:hover {
|
||||
opacity: 100%;
|
||||
color:purple;
|
||||
}
|
||||
@@ -75,6 +75,9 @@ urlpatterns = [
|
||||
path(
|
||||
"accounts/create/", generic_views.create_user, name="create_user"
|
||||
),
|
||||
path(
|
||||
"accounts/trainees/create/", generic_views.create_trainee, name="create_trainee"
|
||||
),
|
||||
path(
|
||||
"accounts/trainees/", generic_views.trainees, name="trainees"
|
||||
),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends 'rapids/base.html' %}
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="question-display-block">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends 'sbas/base.html' %}
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="sbas">
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
<br/>
|
||||
{% if cid %}
|
||||
<a href="{% url 'cid_scores' cid passcode %}">Other exams</a>
|
||||
{% else %}
|
||||
<a href="{% url 'user_scores' %}">Other exams</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
Reference in New Issue
Block a user