Compare commits
4
Commits
4d8d6b2a06
...
af3234bacc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af3234bacc | ||
|
|
7b481c1327 | ||
|
|
41a4aa1a4c | ||
|
|
b8ee207061 |
+1
-1
@@ -684,7 +684,7 @@ class TraineeForm(Form):
|
|||||||
last_name = CharField(max_length=255, required=True)
|
last_name = CharField(max_length=255, required=True)
|
||||||
grade = ModelChoiceField(UserGrades.objects.all(), required=False)
|
grade = ModelChoiceField(UserGrades.objects.all(), required=False)
|
||||||
supervisor = ModelChoiceField(
|
supervisor = ModelChoiceField(
|
||||||
Supervisor.objects.all(), required=False, widget=autocomplete.ModelSelect2(url='generic:supervisor-autocomplete')
|
Supervisor.objects.all().order_by("name"), required=False, widget=autocomplete.ModelSelect2(url='generic:supervisor-autocomplete')
|
||||||
) # Needs to be a user/object ref
|
) # Needs to be a user/object ref
|
||||||
|
|
||||||
#class Meta:
|
#class Meta:
|
||||||
|
|||||||
+1
-1
@@ -1643,7 +1643,7 @@ class Supervisor(models.Model):
|
|||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="If the supervisor has an account on the test system that can be associated here",
|
help_text="If the supervisor has an account on the test system it can be associated here",
|
||||||
)
|
)
|
||||||
site = models.ForeignKey(
|
site = models.ForeignKey(
|
||||||
"Site",
|
"Site",
|
||||||
|
|||||||
+9
-3
@@ -1,3 +1,4 @@
|
|||||||
|
from django.urls import reverse
|
||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from django_tables2.utils import A
|
from django_tables2.utils import A
|
||||||
|
|
||||||
@@ -312,8 +313,9 @@ class SupervisorTable(tables.Table):
|
|||||||
verbose_name="Name",
|
verbose_name="Name",
|
||||||
)
|
)
|
||||||
|
|
||||||
edit = tables.LinkColumn(
|
# We don't use a link column as we want to add a redirect parameter
|
||||||
"generic:supervisor_edit", text="Edit", args=[A("pk")], orderable=False
|
edit = tables.Column(
|
||||||
|
accessor="pk", orderable=False
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -321,4 +323,8 @@ class SupervisorTable(tables.Table):
|
|||||||
template_name = "django_tables2/bootstrap4.html"
|
template_name = "django_tables2/bootstrap4.html"
|
||||||
|
|
||||||
sequence = ("name", "email")
|
sequence = ("name", "email")
|
||||||
exclude = ("id",)
|
exclude = ("id",)
|
||||||
|
|
||||||
|
def render_edit(self, value, record):
|
||||||
|
url = f"{reverse("generic:supervisor_edit", args=[record.pk])}?redirect={self.request.path}"
|
||||||
|
return format_html("<a href='{}'>Edit</a>", url)
|
||||||
@@ -18,7 +18,8 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Edit Supervisor / {{object.cid}}</h2>
|
<h2>Edit Supervisor / {{object.cid}}</h2>
|
||||||
Use this form to create / edit a supervisor
|
<p>Use this form to create / edit a supervisor</p>
|
||||||
|
<p>Trainees can be assigned to a supervisor by editing the trainee and selecting the supervisor from the drop down list.</p>
|
||||||
{% if errors %}
|
{% if errors %}
|
||||||
<div class="alert alert-info" role="alert">{{errors}}</a></div>
|
<div class="alert alert-info" role="alert">{{errors}}</a></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
<a href='{% url "trainees_grade" "ST"|add:i %}'>ST{{i}}</a>{% if not forloop.last %}, {% endif %}
|
<a href='{% url "trainees_grade" "ST"|add:i %}'>ST{{i}}</a>{% if not forloop.last %}, {% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
(<a href="{% url 'create_trainee' %}" title="Click to add a trainee to the platform, creating an account for them.">Add trainee</a>)
|
(<a href="{% url 'create_trainee' %}" title="Click to add a trainee to the platform, creating an account for them.">Add trainee</a>)
|
||||||
|
(<a href="{% url 'accounts_bulk_create' %}" title="Click to create multiple trainees at once.">Bulk create</a>)
|
||||||
|
|
||||||
<h2>
|
<h2>
|
||||||
{% if grade %}
|
{% if grade %}
|
||||||
@@ -23,20 +24,21 @@
|
|||||||
<th>Grade</th><th>Email</th><th>Supervisor</th><th>Edit</th>
|
<th>Grade</th><th>Email</th><th>Supervisor</th><th>Edit</th>
|
||||||
<th class="trainee-bulk-edit">Bulk Edit<br/>
|
<th class="trainee-bulk-edit">Bulk Edit<br/>
|
||||||
<span _="on click log 'test' then log 'hello' then repeat for i in <input/>
|
<span _="on click log 'test' then log 'hello' then repeat for i in <input/>
|
||||||
set i.checked to not i.checked
|
-- set i.checked to not i.checked
|
||||||
|
toggle [@checked] on i
|
||||||
">Toggle All</span>
|
">Toggle All</span>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% for trainee in trainees %}
|
{% for trainee in trainees %}
|
||||||
<tr class="trainee">
|
<tr class="trainee" _="on click log 'test' then log the next <input/> then toggle [@checked] on <input/> in me">
|
||||||
<td>{{trainee.user.first_name}} {{trainee.user.last_name}}</td>
|
<td>{{trainee.user.first_name}} {{trainee.user.last_name}}</td>
|
||||||
<td
|
<td
|
||||||
{% if not trainee.grade %}
|
{% if not trainee.grade %}
|
||||||
class="no-grade"
|
class="no-grade"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
>{{trainee.grade}}{% if not trainee.grade %}
|
>{{trainee.grade}}{% if not trainee.grade %}
|
||||||
<a href="{% url 'account_profile_update' trainee.user.username %}" class="add-grade">add</a>
|
<a href="{% url 'account_profile_update' trainee.user.username %}?redirect={{request.path}}" class="add-grade">add</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>{{trainee.user.email}}</td>
|
<td>{{trainee.user.email}}</td>
|
||||||
@@ -45,7 +47,7 @@
|
|||||||
class="no-supervisor"
|
class="no-supervisor"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
>{{trainee.supervisor}}{% if not trainee.supervisor %}
|
>{{trainee.supervisor}}{% if not trainee.supervisor %}
|
||||||
<a href="{% url 'account_profile_update' trainee.user.username %}" class="add-supervisor">add</a>
|
<a href="{% url 'account_profile_update' trainee.user.username %}?redirect={{request.path}}" class="add-supervisor">add</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td><a href="{% url 'account_update' trainee.user.username %}">User</a>/<a href="{% url 'account_profile_update' trainee.user.username %}">Profile</a>
|
<td><a href="{% url 'account_update' trainee.user.username %}">User</a>/<a href="{% url 'account_profile_update' trainee.user.username %}">Profile</a>
|
||||||
@@ -54,7 +56,7 @@
|
|||||||
></i></span>
|
></i></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="trainee-bulk-edit">
|
<td class="trainee-bulk-edit">
|
||||||
<input type="checkbox" name="trainee" value="{{trainee.user.pk}}">
|
<input type="checkbox" name="selection" value="{{trainee.user.pk}}">
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
@@ -67,11 +69,41 @@
|
|||||||
|
|
||||||
<button class="btn btn-sm"
|
<button class="btn btn-sm"
|
||||||
_="on click toggle .show on .remove-trainee"
|
_="on click toggle .show on .remove-trainee"
|
||||||
>Remove trainees</button>
|
>Remove trainee status</button>
|
||||||
<button class="btn btn-sm"
|
<button class="btn btn-sm"
|
||||||
_="on click toggle .show on .trainee-bulk-edit"
|
_="on click toggle .show on .trainee-bulk-edit"
|
||||||
>Bulk edit trainees</button>
|
>Bulk edit trainees</button>
|
||||||
|
|
||||||
|
<div id="bulk-edit" class="trainee-bulk-edit">
|
||||||
|
<h3>Bulk edit options</h3>
|
||||||
|
These actions will act on all the selected trainees. Refresh the page to cancel / clear.
|
||||||
|
<div id="htmx-info"></div>
|
||||||
|
<div id="htmx-options"></div>
|
||||||
|
<button id="bulk-delete-supervisors-button"
|
||||||
|
title="Deletes the supervisors of all selected users"
|
||||||
|
hx-post="{% url 'generic:users_bulk_delete_supervisors' %}"
|
||||||
|
hx-include="[name='selection']"
|
||||||
|
hx-confirm="This will delete supervisors from all selected users, are you sure you wish to continue?"
|
||||||
|
hx-target="#htmx-info"
|
||||||
|
_='on click put "" into #htmx-options'
|
||||||
|
>Delete supervisors</button>
|
||||||
|
<button id="bulk-edit-grade-button"
|
||||||
|
hx-post="{% url 'generic:users_bulk_edit' %}"
|
||||||
|
hx-include="[name='selection']"
|
||||||
|
hx-target="#htmx-options"
|
||||||
|
title="Changes the selected users grade."
|
||||||
|
|
||||||
|
>Edit grade</button>
|
||||||
|
<button id="bulk-deactivate-user-button"
|
||||||
|
hx-post="{% url 'generic:users_bulk_edit' %}"
|
||||||
|
hx-include="[name='selection']"
|
||||||
|
hx-target="#htmx-options"
|
||||||
|
hx-confirm="This will deactivate all selected users, are you sure you wish to continue?"
|
||||||
|
title="Deactivates the selected users"
|
||||||
|
|
||||||
|
>Deactivate</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.add-supervisor, .add-grade {
|
.add-supervisor, .add-grade {
|
||||||
font-size: small;
|
font-size: small;
|
||||||
@@ -85,8 +117,12 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#bulk-edit {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.show {
|
.show {
|
||||||
display: inline;
|
display: inline !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
td {
|
td {
|
||||||
|
|||||||
+26
-9
@@ -112,6 +112,13 @@ import plotly.express as px
|
|||||||
from django.db.models import Prefetch
|
from django.db.models import Prefetch
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class RedirectMixin():
|
||||||
|
def get_success_url(self) -> str:
|
||||||
|
if "redirect" in self.request.GET:
|
||||||
|
return self.request.GET["redirect"]
|
||||||
|
return super().get_success_url()
|
||||||
|
|
||||||
class AuthorRequiredMixin(object):
|
class AuthorRequiredMixin(object):
|
||||||
def get_object(self, *args, **kwargs):
|
def get_object(self, *args, **kwargs):
|
||||||
obj = super().get_object(*args, **kwargs)
|
obj = super().get_object(*args, **kwargs)
|
||||||
@@ -2616,7 +2623,7 @@ class SupervisorAutocomplete(autocomplete.Select2QuerySetView):
|
|||||||
if not self.request.user.is_authenticated:
|
if not self.request.user.is_authenticated:
|
||||||
return Supervisor.objects.none()
|
return Supervisor.objects.none()
|
||||||
|
|
||||||
qs = Supervisor.objects.all()
|
qs = Supervisor.objects.all().order_by("name")
|
||||||
|
|
||||||
if self.q:
|
if self.q:
|
||||||
# This raises a fielderror which breaks creating a new item if not caught
|
# This raises a fielderror which breaks creating a new item if not caught
|
||||||
@@ -2853,6 +2860,17 @@ def users_bulk_edit(request):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
# TODO: work out how to actually use hyperscript
|
# TODO: work out how to actually use hyperscript
|
||||||
|
html = (
|
||||||
|
html
|
||||||
|
+
|
||||||
|
f"""<button class='change-grade-button' id='add-grade--remove'
|
||||||
|
hx-post="{reverse('generic:users_bulk_edit')}"
|
||||||
|
hx-include="[name='selection']"
|
||||||
|
hx-confirm="This will remove grades of all selected users, are you sure you wish to continue?"
|
||||||
|
hx-target="#htmx-info"
|
||||||
|
_='on click put "" into #htmx-options'
|
||||||
|
>Remove</button>"""
|
||||||
|
)
|
||||||
html = (
|
html = (
|
||||||
html
|
html
|
||||||
+ "<button class='cancel-button' _='on click for el in .change-grade-button remove el end then remove me'>Cancel</button>"
|
+ "<button class='cancel-button' _='on click for el in .change-grade-button remove el end then remove me'>Cancel</button>"
|
||||||
@@ -2861,9 +2879,14 @@ def users_bulk_edit(request):
|
|||||||
case r if r.startswith("add-grade"):
|
case r if r.startswith("add-grade"):
|
||||||
user_models = get_user_selection_from_request(request)
|
user_models = get_user_selection_from_request(request)
|
||||||
|
|
||||||
|
grade = r.split("--")[-1]
|
||||||
|
|
||||||
|
if grade == "remove":
|
||||||
|
grade = None
|
||||||
|
|
||||||
# u: User
|
# u: User
|
||||||
for u in user_models:
|
for u in user_models:
|
||||||
u.userprofile.grade_id = r.split("--")[-1]
|
u.userprofile.grade_id = grade
|
||||||
u.save()
|
u.save()
|
||||||
html = "Grades updated"
|
html = "Grades updated"
|
||||||
case "bulk-add-group-button":
|
case "bulk-add-group-button":
|
||||||
@@ -3464,7 +3487,7 @@ class SupervisorDelete(CidManagerRequiredMixin, DeleteView):
|
|||||||
success_url = reverse_lazy("generic:supervisor")
|
success_url = reverse_lazy("generic:supervisor")
|
||||||
|
|
||||||
|
|
||||||
class SupervisorUpdate(CidManagerRequiredMixin, UpdateView):
|
class SupervisorUpdate(RedirectMixin, CidManagerRequiredMixin, UpdateView):
|
||||||
model = Supervisor
|
model = Supervisor
|
||||||
form_class = SupervisorForm
|
form_class = SupervisorForm
|
||||||
# success_url = reverse_lazy("generic:supervisor_detail", kwargs={'pk': self.pk})
|
# success_url = reverse_lazy("generic:supervisor_detail", kwargs={'pk': self.pk})
|
||||||
@@ -3614,12 +3637,6 @@ class ExamGroupsUpdateBase(
|
|||||||
kwargs.update({"user": self.request.user})
|
kwargs.update({"user": self.request.user})
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
class RedirectMixin():
|
|
||||||
def get_success_url(self) -> str:
|
|
||||||
if "redirect" in self.request.GET:
|
|
||||||
return self.request.GET["redirect"]
|
|
||||||
return super().get_success_url()
|
|
||||||
|
|
||||||
class UpdateQuestionMixin(RedirectMixin, RevisionMixin, UpdateView):
|
class UpdateQuestionMixin(RedirectMixin, RevisionMixin, UpdateView):
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
|
|||||||
@@ -1282,4 +1282,9 @@ tr:has(> td > a) {
|
|||||||
.hover-highlight:hover {
|
.hover-highlight:hover {
|
||||||
opacity: 100%;
|
opacity: 100%;
|
||||||
color:purple;
|
color:purple;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For crispy... */
|
||||||
|
.select2-selection {
|
||||||
|
padding-bottom: 30px;
|
||||||
}
|
}
|
||||||
@@ -72,6 +72,9 @@ urlpatterns = [
|
|||||||
path(
|
path(
|
||||||
"accounts/bulk_create/", views.accounts_bulk_create, name="accounts_bulk_create"
|
"accounts/bulk_create/", views.accounts_bulk_create, name="accounts_bulk_create"
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"accounts/bulk_create/check", views.accounts_bulk_create_check, name="accounts_bulk_create_check"
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"accounts/create/", generic_views.create_user, name="create_user"
|
"accounts/create/", generic_views.create_user, name="create_user"
|
||||||
),
|
),
|
||||||
|
|||||||
+49
-2
@@ -1,5 +1,5 @@
|
|||||||
import secrets
|
import secrets
|
||||||
from typing import Optional
|
from typing import Any, Optional
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from django_tables2 import SingleTableMixin
|
from django_tables2 import SingleTableMixin
|
||||||
@@ -7,7 +7,7 @@ from atlas.models import CaseCollection, CidReportAnswer
|
|||||||
from generic.decorators import user_is_cid_user_manager
|
from generic.decorators import user_is_cid_user_manager
|
||||||
from generic.filters import UserUserFilter
|
from generic.filters import UserUserFilter
|
||||||
from generic.tables import UserUserTable
|
from generic.tables import UserUserTable
|
||||||
from generic.views import CidManagerRequiredMixin, get_question_and_content_type
|
from generic.views import CidManagerRequiredMixin, RedirectMixin, get_question_and_content_type
|
||||||
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
|
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
|
||||||
from django.shortcuts import render, get_object_or_404, redirect
|
from django.shortcuts import render, get_object_or_404, redirect
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
@@ -77,6 +77,8 @@ from django.template import RequestContext
|
|||||||
|
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
|
from dal import autocomplete
|
||||||
|
|
||||||
def feedback_checker(user):
|
def feedback_checker(user):
|
||||||
return user.groups.filter(name="feedback_checker").exists()
|
return user.groups.filter(name="feedback_checker").exists()
|
||||||
|
|
||||||
@@ -655,8 +657,23 @@ class UpdateUserProfileView(UpdateView):
|
|||||||
self.fields = ["grade", "registration_number", "site"]
|
self.fields = ["grade", "registration_number", "site"]
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs: reverse_lazy) -> dict[str, Any]:
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
form = context["form"]
|
||||||
|
|
||||||
|
if "supervisor" in form.fields:
|
||||||
|
#form.fields["supervisor"].queryset = Supervisor.objects.all()
|
||||||
|
form.fields["supervisor"] = forms.ModelChoiceField(
|
||||||
|
Supervisor.objects.all().order_by("name"), required=False, widget=autocomplete.ModelSelect2(url='generic:supervisor-autocomplete')
|
||||||
|
)
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
|
if "redirect" in self.request.GET:
|
||||||
|
return self.request.GET["redirect"]
|
||||||
|
|
||||||
if self.request.user.is_superuser or self.request.user.groups.filter(name="cid_user_manager").exists():
|
if self.request.user.is_superuser or self.request.user.groups.filter(name="cid_user_manager").exists():
|
||||||
view_name = "account_profile"
|
view_name = "account_profile"
|
||||||
# No need for reverse_lazy here, because it's called inside the method
|
# No need for reverse_lazy here, because it's called inside the method
|
||||||
@@ -713,6 +730,35 @@ def accounts_check_users(request):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@user_is_cid_user_manager
|
||||||
|
def accounts_bulk_create_check(request):
|
||||||
|
if not request.method == "POST":
|
||||||
|
return HttpResponse("Invalid request")
|
||||||
|
|
||||||
|
user = json.loads(request.POST.get("user"))
|
||||||
|
|
||||||
|
if User.objects.filter(username=user["email"]).exists():
|
||||||
|
return HttpResponse(format_html("<span class='error'>{}</span>", "User already exists"))
|
||||||
|
|
||||||
|
if not UserGrades.objects.filter(name=user["grade"]):
|
||||||
|
return HttpResponse(format_html("<span class='error'>{}</span>", "Invalid grade"))
|
||||||
|
|
||||||
|
if "supervisor_email" in user:
|
||||||
|
supervisor = Supervisor.objects.filter(email=user["supervisor_email"])
|
||||||
|
|
||||||
|
if not supervisor:
|
||||||
|
return HttpResponse("Ok, supervisor will be created")
|
||||||
|
|
||||||
|
if supervisor.count() > 1:
|
||||||
|
return HttpResponse(format_html("<span class='error'>{}</span>", "More than one supervisor with that email"))
|
||||||
|
|
||||||
|
if supervisor.first().name != user["supervisor_name"]:
|
||||||
|
return HttpResponse(format_html("<span class='error'>{}</span>", "Supervisor name does not match"))
|
||||||
|
|
||||||
|
return HttpResponse("OK, supervisor exists")
|
||||||
|
|
||||||
|
return HttpResponse("OK")
|
||||||
|
|
||||||
|
|
||||||
@user_is_cid_user_manager
|
@user_is_cid_user_manager
|
||||||
def accounts_bulk_create(request):
|
def accounts_bulk_create(request):
|
||||||
@@ -764,6 +810,7 @@ def accounts_bulk_create(request):
|
|||||||
try:
|
try:
|
||||||
user_profile = UserProfile.objects.get(user=new_user)
|
user_profile = UserProfile.objects.get(user=new_user)
|
||||||
user_profile.peninsula_trainee = True
|
user_profile.peninsula_trainee = True
|
||||||
|
# TODO: check supervisor details are correct
|
||||||
if "supervisor_email" in user and "supervisor_name" in user:
|
if "supervisor_email" in user and "supervisor_name" in user:
|
||||||
s, created = Supervisor.objects.get_or_create(
|
s, created = Supervisor.objects.get_or_create(
|
||||||
email=user["supervisor_email"],
|
email=user["supervisor_email"],
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<p>Please note users created this way bypass some of the validations so check details such as email addresses are correct</p>
|
<p>Please note users created this way bypass some of the validations so check details such as email addresses are correct</p>
|
||||||
<textarea id="csv" placeholder="Paste users content here" style="width: 300px; height: 100px;"></textarea><br/>
|
<textarea id="csv" placeholder="Paste users content here" style="width: 300px; height: 100px;"></textarea><br/>
|
||||||
<input type="button" value="Load Data" onclick="createTable()" >
|
<input type="button" value="Load Data" _="on click createTable()" >
|
||||||
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@@ -101,7 +101,14 @@
|
|||||||
myTbody.appendChild(myRow);
|
myTbody.appendChild(myRow);
|
||||||
users.push(user)
|
users.push(user)
|
||||||
emails.push(user.email)
|
emails.push(user.email)
|
||||||
$("#users-list").append(`<li>Name: ${user.first_name} ${user.last_name}<br/>Email: ${user.email}<br/>Grade: ${user.grade}<br/>Supervisor: ${user.supervisor_name}<br/>Supervisor email: ${user.supervisor_email}</li>`)
|
$("#users-list").append(`<li>Name: ${user.first_name} ${user.last_name}<br/>Email: ${user.email}<br/>Grade: ${user.grade}<br/>Supervisor: ${user.supervisor_name}<br/>Supervisor email: ${user.supervisor_email}<br/><button
|
||||||
|
hx-post="{% url 'accounts_bulk_create_check' %}"
|
||||||
|
hx-trigger="load"
|
||||||
|
hx-target="next span"
|
||||||
|
name="user"
|
||||||
|
class="hide"
|
||||||
|
value='${JSON.stringify(user)}'
|
||||||
|
>CHECK</button><span class="check-status"></span></li>`)
|
||||||
}
|
}
|
||||||
myTable.appendChild(myTbody);
|
myTable.appendChild(myTbody);
|
||||||
|
|
||||||
@@ -112,6 +119,10 @@
|
|||||||
|
|
||||||
$("#users-list").append(`${users.length} users to create.`)
|
$("#users-list").append(`${users.length} users to create.`)
|
||||||
|
|
||||||
|
// Make sure the new hyperscript works
|
||||||
|
_hyperscript.processNode($("#users-list")[0]);
|
||||||
|
htmx.process($("#users-list")[0]);
|
||||||
|
|
||||||
$("#user-list-json").val(JSON.stringify(users));
|
$("#user-list-json").val(JSON.stringify(users));
|
||||||
$("#submit-users").show();
|
$("#submit-users").show();
|
||||||
|
|
||||||
@@ -143,5 +154,18 @@
|
|||||||
margin: 10px;
|
margin: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.check-status {
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color:red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#users-list li:has(.error) {
|
||||||
|
border: 1px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
{% load auth_extras %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<p>
|
<p>
|
||||||
<div class="anatomy">
|
<div class="anatomy">
|
||||||
@@ -53,7 +53,8 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{% if request.user.is_staff %}
|
{% if request.user|has_group:"cid_user_manager" %}
|
||||||
|
Manage <a href="{% url 'trainees' %}">trainees</a><br/>
|
||||||
Manage users <a href="{% url 'accounts_list'%}">here</a> and candidates <a href="{% url 'generic:manage_cids'%}">here</a>
|
Manage users <a href="{% url 'accounts_list'%}">here</a> and candidates <a href="{% url 'generic:manage_cids'%}">here</a>
|
||||||
|
|
||||||
<p>Manage <a href="{% url 'generic:examination_view' %}">Examinations</a>
|
<p>Manage <a href="{% url 'generic:examination_view' %}">Examinations</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user