Add grade information to user search results and enhance user addition functionality
This commit is contained in:
+28
-4
@@ -658,7 +658,29 @@ class UserUserGroupForm(ModelForm):
|
||||
timeout = setTimeout(() => fetchResults(search.value), 50);
|
||||
}});
|
||||
|
||||
window.addUserToField = function(fieldName, id, text) {{
|
||||
// fieldName for this widget instance
|
||||
const widgetFieldName = '{self.name}';
|
||||
|
||||
// Add button click delegation: results list buttons have data attributes
|
||||
results.addEventListener('click', function(e) {{
|
||||
const btn = e.target.closest('.user-add-btn');
|
||||
if (!btn) return;
|
||||
const id = btn.getAttribute('data-user-id');
|
||||
const text = btn.getAttribute('data-user-text') || btn.textContent.trim();
|
||||
const grade = btn.getAttribute('data-user-grade') || '';
|
||||
addUserToField(widgetFieldName, id, text, grade);
|
||||
}});
|
||||
|
||||
// Wire up the "Add all results" button if present
|
||||
const addAllBtn = results.parentElement.querySelector('.user-add-all-btn');
|
||||
if (addAllBtn) {
|
||||
addAllBtn.addEventListener('click', function(e) {{
|
||||
e.preventDefault();
|
||||
addAllFromResults(widgetFieldName);
|
||||
}});
|
||||
}
|
||||
|
||||
window.addUserToField = function(fieldName, id, text, grade) {{
|
||||
const sel = document.getElementById('id_' + fieldName);
|
||||
if (!sel) return;
|
||||
// prevent duplicate
|
||||
@@ -666,11 +688,12 @@ class UserUserGroupForm(ModelForm):
|
||||
const opt = document.createElement('option'); opt.value = id; opt.selected = true; opt.text = text;
|
||||
sel.appendChild(opt);
|
||||
|
||||
// add to visible list
|
||||
// add to visible list (include grade if provided)
|
||||
const li = document.createElement('li');
|
||||
li.className = 'list-group-item d-flex justify-content-between align-items-center';
|
||||
li.id = 'selected_user_' + fieldName + '_' + id;
|
||||
const span = document.createElement('span'); span.innerHTML = text;
|
||||
const span = document.createElement('span');
|
||||
span.innerHTML = text + (grade ? ' <small class="text-muted ms-2">' + grade + '</small>' : '');
|
||||
const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'btn btn-sm btn-outline-danger ms-2'; btn.innerText = 'Remove';
|
||||
btn.addEventListener('click', function() {{ removeUserFromField(fieldName, id); }});
|
||||
li.appendChild(span); li.appendChild(btn);
|
||||
@@ -692,7 +715,8 @@ class UserUserGroupForm(ModelForm):
|
||||
items.forEach(function(it) {{
|
||||
const id = it.getAttribute('data-user-id');
|
||||
const text = it.getAttribute('data-user-text') || it.textContent.trim();
|
||||
addUserToField(fieldName, id, text);
|
||||
const grade = it.getAttribute('data-user-grade') || '';
|
||||
addUserToField(fieldName, id, text, grade);
|
||||
}});
|
||||
}}
|
||||
}})();
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
{% if results %}
|
||||
<ul class="list-unstyled mb-0" id="user_search_results_list_{{ field }}">
|
||||
{% for item in results %}
|
||||
<li class="py-1 d-flex justify-content-between align-items-center" data-user-id="{{ item.id }}" data-user-text="{{ item.text|escapejs }}">
|
||||
<div class="flex-grow-1">{{ item.text|escape }}</div>
|
||||
<li class="py-1 d-flex justify-content-between align-items-center" data-user-id="{{ item.id }}" data-user-text="{{ item.text|escapejs }}" data-user-grade="{{ item.grade|default_if_none:''|escapejs }}">
|
||||
<div class="flex-grow-1">
|
||||
{{ item.text|escape }}
|
||||
{% if item.grade %}
|
||||
<small class="text-muted ms-2">{{ item.grade|escape }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="btn btn-sm btn-primary" onclick="addUserToField('{{ field }}', {{ item.id }}, '{{ item.text|escapejs }}')">Add</button>
|
||||
<button type="button" class="btn btn-sm btn-primary user-add-btn" data-user-id="{{ item.id }}" data-user-text="{{ item.text|escapejs }}" data-user-grade="{{ item.grade|default_if_none:''|escapejs }}">Add</button>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if results %}
|
||||
<div class="mt-2 text-end">
|
||||
<button type="button" class="btn btn-sm btn-outline-success" onclick="addAllFromResults('{{ field }}')">Add all results</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-success user-add-all-btn" data-field="{{ field }}">Add all results</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
|
||||
+19
-4
@@ -6017,10 +6017,25 @@ def user_search_widget(request):
|
||||
limit = 50 if q in ("*", "%") or q_raw in ("*", "%") else 10
|
||||
users_qs = users_qs.order_by("last_name", "first_name")[:limit]
|
||||
|
||||
results = [
|
||||
{"id": u.pk, "text": f"{u.get_full_name() or u.username} - {u.email or ''}"}
|
||||
for u in users_qs
|
||||
]
|
||||
results = []
|
||||
for u in users_qs:
|
||||
grade = ""
|
||||
try:
|
||||
up = getattr(u, "userprofile", None)
|
||||
if up and getattr(up, "grade", None):
|
||||
# grade may be a FK object or a simple string depending on model
|
||||
g = up.grade
|
||||
grade = getattr(g, "name", str(g)) if g is not None else ""
|
||||
except Exception:
|
||||
grade = ""
|
||||
|
||||
results.append(
|
||||
{
|
||||
"id": u.pk,
|
||||
"text": f"{u.get_full_name() or u.username} - {u.email or ''}",
|
||||
"grade": grade,
|
||||
}
|
||||
)
|
||||
|
||||
return render(
|
||||
request,
|
||||
|
||||
Reference in New Issue
Block a user