a number of updates

This commit is contained in:
Ross
2023-09-08 18:10:42 +01:00
parent 98a874f805
commit 297f8619b4
5 changed files with 198 additions and 105 deletions
+8 -2
View File
@@ -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
+29 -10
View File
@@ -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 %}
+113 -66
View File
@@ -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,83 +2473,131 @@ 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)
match request.htmx.trigger:
case r if r is None:
return HttpResponse("None", content_type="text/html")
case "bulk-edit-grade-button": try:
user_grades = UserGrades.objects.all() match request.htmx.trigger:
case r if r is None:
html = "None"
case "bulk-deactivate-user-button":
user_models = get_user_selection_from_request(request)
html = "".join( # u: User
[ for u in user_models:
f"""<button class='change-grade-button' id='add-grade--{grade.id}' u.is_active = False
hx-post="{reverse('generic:users_bulk_edit')}" u.save()
hx-include="[name='selection']"
hx-confirm="This will modify grades of all selected users, are you sure you wish to continue?"
hx-target="#htmx-info"
>{grade.name}</button>"""
for grade in user_grades
]
)
# TODO: work out how to actually use hyperscript
html = (
html
+ "<button _='on click for el in .change-grade-button remove el end then remove me'>Cancel</button>"
)
return HttpResponse(html, content_type="text/html") html = "Users deactivated"
case r if r.startswith("add-grade"):
selected_users = request.POST.getlist("selection")
if not selected_users: case "bulk-edit-grade-button":
return HttpResponse("No users selected", content_type="text/html") user_grades = UserGrades.objects.all()
user_models = User.objects.filter(id__in=selected_users)
# u: User html = "".join(
for u in user_models: [
u.userprofile.grade_id = r.split("--")[-1] f"""<button class='change-grade-button' id='add-grade--{grade.id}'
u.save() hx-post="{reverse('generic:users_bulk_edit')}"
return HttpResponse("Grades update", content_type="text/html") hx-include="[name='selection']"
case "bulk-add-group-button": hx-confirm="This will modify grades of all selected users, are you sure you wish to continue?"
user_groups = UserUserGroup.objects.all() hx-target="#htmx-info"
_='on click put "" into #htmx-options'
>{grade.name}</button>"""
for grade in user_grades
]
)
# TODO: work out how to actually use hyperscript
html = (
html
+ "<button class='cancel-button' _='on click for el in .change-grade-button remove el end then remove me'>Cancel</button>"
)
html = "".join( case r if r.startswith("add-grade"):
[ user_models = get_user_selection_from_request(request)
f"""<button class='add-group-button' id='add-group--{group.id}'
hx-post="{reverse('generic:users_bulk_edit')}"
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-target="#htmx-info"
>{group.name}</button>"""
for group in user_groups
]
)
# TODO: work out how to actually use hyperscript
html = (
html
+ "<button _='on click for el in .add-group-button remove el end then remove me'>Cancel</button>"
)
return HttpResponse(html, content_type="text/html") # u: User
case r if r.startswith("add-group"): for u in user_models:
selected_users = request.POST.getlist("selection") u.userprofile.grade_id = r.split("--")[-1]
u.save()
html = "Grades updated"
case "bulk-add-group-button":
user_groups = UserUserGroup.objects.all()
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='add-group-button' id='add-group--{group.id}'
hx-post="{reverse('generic:users_bulk_edit')}"
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-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>"
)
# u: User case "bulk-remove-group-button":
for u in user_models: user_groups = UserUserGroup.objects.all()
pass
u.user_groups.add(r.split("--")[-1]) html = "".join(
u.save() [
return HttpResponse("Group added", content_type="text/html") f"""<button class='remove-group-button' id='remove-group--{group.id}'
case _: hx-post="{reverse('generic:users_bulk_edit')}"
return HttpResponse("Error", content_type="text/html") 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
for u in user_models:
pass
u.user_groups.add(r.split("--")[-1])
u.save()
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 _:
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
+47 -26
View File
@@ -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%;
@@ -758,7 +759,7 @@ input {
.sba-finish-list a { .sba-finish-list a {
text-decoration: none; text-decoration: none;
color: unset; color: unset;
} }
.sba-finish-list span { .sba-finish-list span {
@@ -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,17 +933,17 @@ 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;
} }
.alert-error { .alert-error {
border: 1px dashed red; border: 1px dashed red;
} }
@@ -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,24 +995,23 @@ 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;
} }
.self-feedback-block { .self-feedback-block {
@@ -1018,4 +1026,17 @@ h1, h2, h3, h4, h5, h6 {
.collection-name-blend { .collection-name-blend {
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
View File
@@ -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"