a number of updates
This commit is contained in:
+8
-2
@@ -50,6 +50,7 @@ class UserUserFilter(django_filters.FilterSet):
|
|||||||
#"userprofile__grade": ["exact"],
|
#"userprofile__grade": ["exact"],
|
||||||
#"userprofile__supervisor": ["exact"],
|
#"userprofile__supervisor": ["exact"],
|
||||||
"email": ["contains"],
|
"email": ["contains"],
|
||||||
|
"is_active": ["exact"]
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -57,11 +58,16 @@ class UserUserFilter(django_filters.FilterSet):
|
|||||||
parent = super().qs
|
parent = super().qs
|
||||||
|
|
||||||
## filter_active = getattr(self.request, 'active', True)
|
## filter_active = getattr(self.request, 'active', True)
|
||||||
#if "active" not in self.request.GET:
|
if "is_active" not in self.request.GET:
|
||||||
# return parent.filter(active=True)
|
return parent.filter(is_active=True)
|
||||||
|
|
||||||
return parent
|
return parent
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(UserUserFilter, self).__init__(*args, **kwargs)
|
||||||
|
self.form.initial['is_active'] = True
|
||||||
|
|
||||||
|
|
||||||
class ExaminationFilter(django_filters.FilterSet):
|
class ExaminationFilter(django_filters.FilterSet):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Examination
|
model = Examination
|
||||||
|
|||||||
@@ -18,16 +18,7 @@
|
|||||||
</details>
|
</details>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="table-div">
|
<details class="bulk-edit">
|
||||||
<span id="manage-span">
|
|
||||||
{% render_table table %}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a href="{% url 'accounts_bulk_create' %}">Bulk create users</a>
|
|
||||||
<a href="{% url 'create_user' %}">Create single user</a>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>
|
<summary>
|
||||||
Bulk edit
|
Bulk edit
|
||||||
</summary>
|
</summary>
|
||||||
@@ -39,19 +30,47 @@
|
|||||||
hx-include="[name='selection']"
|
hx-include="[name='selection']"
|
||||||
hx-confirm="This will delete supervisors from all selected users, are you sure you wish to continue?"
|
hx-confirm="This will delete supervisors from all selected users, are you sure you wish to continue?"
|
||||||
hx-target="#htmx-info"
|
hx-target="#htmx-info"
|
||||||
|
_='on click put "" into #htmx-options'
|
||||||
>Delete supervisors</button>
|
>Delete supervisors</button>
|
||||||
<button id="bulk-edit-grade-button"
|
<button id="bulk-edit-grade-button"
|
||||||
hx-post="{% url 'generic:users_bulk_edit' %}"
|
hx-post="{% url 'generic:users_bulk_edit' %}"
|
||||||
hx-include="[name='selection']"
|
hx-include="[name='selection']"
|
||||||
hx-target="#htmx-options"
|
hx-target="#htmx-options"
|
||||||
|
title="Changes the selected users grade."
|
||||||
|
|
||||||
>Edit grade</button>
|
>Edit grade</button>
|
||||||
<button id="bulk-add-group-button"
|
<button id="bulk-add-group-button"
|
||||||
hx-post="{% url 'generic:users_bulk_edit' %}"
|
hx-post="{% url 'generic:users_bulk_edit' %}"
|
||||||
hx-include="[name='selection']"
|
hx-include="[name='selection']"
|
||||||
hx-target="#htmx-options"
|
hx-target="#htmx-options"
|
||||||
|
title="Adds the selected user to a group."
|
||||||
|
|
||||||
>Add group</button>
|
>Add group</button>
|
||||||
|
<button id="bulk-remove-group-button"
|
||||||
|
hx-post="{% url 'generic:users_bulk_edit' %}"
|
||||||
|
hx-include="[name='selection']"
|
||||||
|
hx-target="#htmx-options"
|
||||||
|
title="Removes the selected user from a group."
|
||||||
|
|
||||||
|
>Remove group</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>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
<div id="table-div">
|
||||||
|
<span id="manage-span">
|
||||||
|
{% render_table table %}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a href="{% url 'accounts_bulk_create' %}">Bulk create users</a>
|
||||||
|
<a href="{% url 'create_user' %}">Create single user</a>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
+67
-20
@@ -208,7 +208,6 @@ def examination_merge(request, pk):
|
|||||||
if examination.merge_into(examination_to_merge_into):
|
if examination.merge_into(examination_to_merge_into):
|
||||||
success = True
|
success = True
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
examination_to_merge_into = False
|
examination_to_merge_into = False
|
||||||
return render(
|
return render(
|
||||||
@@ -218,7 +217,7 @@ def examination_merge(request, pk):
|
|||||||
"form": form,
|
"form": form,
|
||||||
"examination": examination,
|
"examination": examination,
|
||||||
"examination_to_merge_into": examination_to_merge_into,
|
"examination_to_merge_into": examination_to_merge_into,
|
||||||
"success": success
|
"success": success,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -2474,13 +2473,37 @@ def users_bulk_delete_supervisors(request):
|
|||||||
return HttpResponse("No users selected", content_type="text/plain")
|
return HttpResponse("No users selected", content_type="text/plain")
|
||||||
|
|
||||||
|
|
||||||
|
class NoUsersSelected(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_selection_from_request(request):
|
||||||
|
selected_users = request.POST.getlist("selection")
|
||||||
|
|
||||||
|
if not selected_users:
|
||||||
|
raise NoUsersSelected
|
||||||
|
user_models = User.objects.filter(id__in=selected_users)
|
||||||
|
return user_models
|
||||||
|
|
||||||
|
|
||||||
@user_is_cid_user_manager
|
@user_is_cid_user_manager
|
||||||
def users_bulk_edit(request):
|
def users_bulk_edit(request):
|
||||||
print(request.htmx.trigger)
|
print(request.htmx.trigger)
|
||||||
print(request.htmx.trigger_name)
|
print(request.htmx.trigger_name)
|
||||||
|
|
||||||
|
try:
|
||||||
match request.htmx.trigger:
|
match request.htmx.trigger:
|
||||||
case r if r is None:
|
case r if r is None:
|
||||||
return HttpResponse("None", content_type="text/html")
|
html = "None"
|
||||||
|
case "bulk-deactivate-user-button":
|
||||||
|
user_models = get_user_selection_from_request(request)
|
||||||
|
|
||||||
|
# u: User
|
||||||
|
for u in user_models:
|
||||||
|
u.is_active = False
|
||||||
|
u.save()
|
||||||
|
|
||||||
|
html = "Users deactivated"
|
||||||
|
|
||||||
case "bulk-edit-grade-button":
|
case "bulk-edit-grade-button":
|
||||||
user_grades = UserGrades.objects.all()
|
user_grades = UserGrades.objects.all()
|
||||||
@@ -2492,6 +2515,7 @@ def users_bulk_edit(request):
|
|||||||
hx-include="[name='selection']"
|
hx-include="[name='selection']"
|
||||||
hx-confirm="This will modify grades of all selected users, are you sure you wish to continue?"
|
hx-confirm="This will modify grades of all selected users, are you sure you wish to continue?"
|
||||||
hx-target="#htmx-info"
|
hx-target="#htmx-info"
|
||||||
|
_='on click put "" into #htmx-options'
|
||||||
>{grade.name}</button>"""
|
>{grade.name}</button>"""
|
||||||
for grade in user_grades
|
for grade in user_grades
|
||||||
]
|
]
|
||||||
@@ -2499,22 +2523,17 @@ def users_bulk_edit(request):
|
|||||||
# TODO: work out how to actually use hyperscript
|
# TODO: work out how to actually use hyperscript
|
||||||
html = (
|
html = (
|
||||||
html
|
html
|
||||||
+ "<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>"
|
||||||
)
|
)
|
||||||
|
|
||||||
return HttpResponse(html, content_type="text/html")
|
|
||||||
case r if r.startswith("add-grade"):
|
case r if r.startswith("add-grade"):
|
||||||
selected_users = request.POST.getlist("selection")
|
user_models = get_user_selection_from_request(request)
|
||||||
|
|
||||||
if not selected_users:
|
|
||||||
return HttpResponse("No users selected", content_type="text/html")
|
|
||||||
user_models = User.objects.filter(id__in=selected_users)
|
|
||||||
|
|
||||||
# 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 = r.split("--")[-1]
|
||||||
u.save()
|
u.save()
|
||||||
return HttpResponse("Grades update", content_type="text/html")
|
html = "Grades updated"
|
||||||
case "bulk-add-group-button":
|
case "bulk-add-group-button":
|
||||||
user_groups = UserUserGroup.objects.all()
|
user_groups = UserUserGroup.objects.all()
|
||||||
|
|
||||||
@@ -2525,6 +2544,7 @@ def users_bulk_edit(request):
|
|||||||
hx-include="[name='selection']"
|
hx-include="[name='selection']"
|
||||||
hx-confirm="This will add the group '{group.name}' to all selected users, are you sure you wish to continue?"
|
hx-confirm="This will add the group '{group.name}' to all selected users, are you sure you wish to continue?"
|
||||||
hx-target="#htmx-info"
|
hx-target="#htmx-info"
|
||||||
|
_='on click put "" into #htmx-options'
|
||||||
>{group.name}</button>"""
|
>{group.name}</button>"""
|
||||||
for group in user_groups
|
for group in user_groups
|
||||||
]
|
]
|
||||||
@@ -2532,25 +2552,52 @@ def users_bulk_edit(request):
|
|||||||
# TODO: work out how to actually use hyperscript
|
# TODO: work out how to actually use hyperscript
|
||||||
html = (
|
html = (
|
||||||
html
|
html
|
||||||
+ "<button _='on click for el in .add-group-button remove el end then remove me'>Cancel</button>"
|
+ "<button class='cancel-button'_='on click for el in .add-group-button remove el end then remove me'>Cancel</button>"
|
||||||
)
|
)
|
||||||
|
|
||||||
return HttpResponse(html, content_type="text/html")
|
case "bulk-remove-group-button":
|
||||||
case r if r.startswith("add-group"):
|
user_groups = UserUserGroup.objects.all()
|
||||||
selected_users = request.POST.getlist("selection")
|
|
||||||
|
|
||||||
if not selected_users:
|
html = "".join(
|
||||||
return HttpResponse("No users selected", content_type="text/html")
|
[
|
||||||
user_models = User.objects.filter(id__in=selected_users)
|
f"""<button class='remove-group-button' id='remove-group--{group.id}'
|
||||||
|
hx-post="{reverse('generic:users_bulk_edit')}"
|
||||||
|
hx-include="[name='selection']"
|
||||||
|
hx-confirm="This will remove the group '{group.name}' from all selected users, are you sure you wish to continue?"
|
||||||
|
hx-target="#htmx-info"
|
||||||
|
_='on click put "" into #htmx-options'
|
||||||
|
>{group.name}</button>"""
|
||||||
|
for group in user_groups
|
||||||
|
]
|
||||||
|
)
|
||||||
|
# TODO: work out how to actually use hyperscript
|
||||||
|
html = (
|
||||||
|
html
|
||||||
|
+ "<button class='cancel-button'_='on click for el in .add-group-button remove el end then remove me'>Cancel</button>"
|
||||||
|
)
|
||||||
|
|
||||||
|
case r if r.startswith("add-group"):
|
||||||
|
user_models = get_user_selection_from_request(request)
|
||||||
|
|
||||||
# u: User
|
# u: User
|
||||||
for u in user_models:
|
for u in user_models:
|
||||||
pass
|
pass
|
||||||
u.user_groups.add(r.split("--")[-1])
|
u.user_groups.add(r.split("--")[-1])
|
||||||
u.save()
|
u.save()
|
||||||
return HttpResponse("Group added", content_type="text/html")
|
html = "Group added"
|
||||||
|
case r if r.startswith("remove-group"):
|
||||||
|
user_models = get_user_selection_from_request(request)
|
||||||
|
|
||||||
|
# u: User
|
||||||
|
for u in user_models:
|
||||||
|
group_id = r.split("--")[-1]
|
||||||
|
u.user_groups.remove(group_id)
|
||||||
|
html = "Group removed"
|
||||||
case _:
|
case _:
|
||||||
return HttpResponse("Error", content_type="text/html")
|
html = "None"
|
||||||
|
return HttpResponse(html, content_type="text/html")
|
||||||
|
except NoUsersSelected:
|
||||||
|
return HttpResponse("No users selected", content_type="text/html")
|
||||||
|
|
||||||
|
|
||||||
@user_is_cid_user_manager
|
@user_is_cid_user_manager
|
||||||
|
|||||||
+38
-17
@@ -588,6 +588,7 @@ td.user-answer-score-2.rapid-ans::after {
|
|||||||
.series-block-popup-link {
|
.series-block-popup-link {
|
||||||
font-size: smaller;
|
font-size: smaller;
|
||||||
}
|
}
|
||||||
|
|
||||||
.series-block-popup-link a {
|
.series-block-popup-link a {
|
||||||
color: rgb(0, 153, 255);
|
color: rgb(0, 153, 255);
|
||||||
opacity: 50%;
|
opacity: 50%;
|
||||||
@@ -915,7 +916,10 @@ summary h5 {
|
|||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button a, button a:link, button a:visited, button a:hover {
|
button a,
|
||||||
|
button a:link,
|
||||||
|
button a:visited,
|
||||||
|
button a:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
@@ -929,11 +933,11 @@ details.filter {
|
|||||||
/* Generic default styling for forms */
|
/* Generic default styling for forms */
|
||||||
|
|
||||||
/* Highlight form errors */
|
/* Highlight form errors */
|
||||||
tr:has(.errorlist){
|
tr:has(.errorlist) {
|
||||||
border: 1px dashed red;
|
border: 1px dashed red;
|
||||||
}
|
}
|
||||||
|
|
||||||
.errorlist + input {
|
.errorlist+input {
|
||||||
background-color: red;
|
background-color: red;
|
||||||
color: darkblue;
|
color: darkblue;
|
||||||
}
|
}
|
||||||
@@ -954,7 +958,7 @@ tr:has(.errorlist){
|
|||||||
opacity: 25%;
|
opacity: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-group:hover .help-block{
|
.control-group:hover .help-block {
|
||||||
opacity: 100%;
|
opacity: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -971,7 +975,12 @@ form .submit-button {
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -986,22 +995,21 @@ h1, h2, h3, h4, h5, h6 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.cid-candidate-list div {
|
.cid-candidate-list div {}
|
||||||
}
|
|
||||||
|
|
||||||
.stamp-white {
|
.stamp-white {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
z-index:1;
|
z-index: 1;
|
||||||
font-family:Arial,sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
transform: rotate(-15deg);
|
transform: rotate(-15deg);
|
||||||
font-size:20px;
|
font-size: 20px;
|
||||||
color:white;
|
color: white;
|
||||||
border:solid 2px white;
|
border: solid 2px white;
|
||||||
padding:5px;
|
padding: 5px;
|
||||||
border-radius:5px;
|
border-radius: 5px;
|
||||||
zoom:1;
|
zoom: 1;
|
||||||
filter:alpha(opacity=20);
|
filter: alpha(opacity=20);
|
||||||
opacity:0.9;
|
opacity: 0.9;
|
||||||
text-shadow: 0 0 2px white;
|
text-shadow: 0 0 2px white;
|
||||||
box-shadow: 0 0 2px white;
|
box-shadow: 0 0 2px white;
|
||||||
}
|
}
|
||||||
@@ -1019,3 +1027,16 @@ h1, h2, h3, h4, h5, h6 {
|
|||||||
opacity: 70%;
|
opacity: 70%;
|
||||||
font-size: small;
|
font-size: small;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cancel-button {
|
||||||
|
color: darkblue;
|
||||||
|
border-color: darkblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bulk-edit {
|
||||||
|
position: sticky;
|
||||||
|
top: 0px;
|
||||||
|
background-color: black;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
}
|
||||||
+1
-1
@@ -588,7 +588,7 @@ class DeleteUserView(CidManagerRequiredMixin, DeleteView):
|
|||||||
|
|
||||||
class UpdateUserView(CidManagerRequiredMixin, UpdateView):
|
class UpdateUserView(CidManagerRequiredMixin, UpdateView):
|
||||||
model = User
|
model = User
|
||||||
fields = ["first_name", "last_name", "email"] # Keep listing whatever fields
|
fields = ["first_name", "last_name", "email", "is_active"] # Keep listing whatever fields
|
||||||
# the combined UserProfile and User exposes.
|
# the combined UserProfile and User exposes.
|
||||||
template_name = "user_update.html"
|
template_name = "user_update.html"
|
||||||
slug_field = "username"
|
slug_field = "username"
|
||||||
|
|||||||
Reference in New Issue
Block a user