Modal: multi-select projects and teams via Choices.js
Replaces the two single <select> elements in the report config modal with <select multiple> enhanced by Choices.js (CDN 10.2.0, admin-only gated, graceful fallback to native on CDN failure). Removes the 'All Projects' / 'All Teams' placeholder option rows — empty selection = all, matching Choices.js convention. Persists selected values across submissions via two new context keys (selected_project_ids, selected_team_ids) threaded through index() and generate_report(). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
16d192d5fc
commit
748c7c79d7
@ -61,20 +61,18 @@
|
||||
<!-- Project Filter (optional) -->
|
||||
<div class="col-12">
|
||||
<label class="form-label fw-semibold">Project <span class="text-muted fw-normal">(optional)</span></label>
|
||||
<select name="project" class="form-select">
|
||||
<option value="">All Projects</option>
|
||||
<select name="project" class="form-select report-multi" multiple data-placeholder="All projects (leave empty for all)">
|
||||
{% for p in projects %}
|
||||
<option value="{{ p.id }}">{{ p.name }}</option>
|
||||
<option value="{{ p.id }}"{% if p.id|stringformat:"s" in selected_project_ids %} selected{% endif %}>{{ p.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<!-- Team Filter (optional) -->
|
||||
<div class="col-12">
|
||||
<label class="form-label fw-semibold">Team <span class="text-muted fw-normal">(optional)</span></label>
|
||||
<select name="team" class="form-select">
|
||||
<option value="">All Teams</option>
|
||||
<select name="team" class="form-select report-multi" multiple data-placeholder="All teams (leave empty for all)">
|
||||
{% for t in teams %}
|
||||
<option value="{{ t.id }}">{{ t.name }}</option>
|
||||
<option value="{{ t.id }}"{% if t.id|stringformat:"s" in selected_team_ids %} selected{% endif %}>{{ t.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
@ -132,3 +130,25 @@
|
||||
if (modeCustom) modeCustom.addEventListener('change', toggleMode);
|
||||
})();
|
||||
</script>
|
||||
|
||||
{# === CHOICES.JS — multi-select enhancement (admin-only) === #}
|
||||
{# Loaded CDN-only; falls back to native <select multiple> if the CDN fails. #}
|
||||
{% if user.is_staff or user.is_superuser %}
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/choices.js@10.2.0/public/assets/styles/choices.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/choices.js@10.2.0/public/assets/scripts/choices.min.js" defer></script>
|
||||
<script>
|
||||
(function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof Choices === 'undefined') return; // graceful fallback
|
||||
document.querySelectorAll('.report-multi').forEach(function(el) {
|
||||
new Choices(el, {
|
||||
removeItemButton: true,
|
||||
shouldSort: false,
|
||||
placeholder: true,
|
||||
placeholderValue: el.getAttribute('data-placeholder') || '',
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
@ -430,6 +430,9 @@ def index(request):
|
||||
'certs_expired_count': certs_expired_count,
|
||||
'certs_expiring_count': certs_expiring_count,
|
||||
'certs_alert_total': certs_alert_total,
|
||||
# Empty on the home dashboard — modal opens clean (no pre-selected filters)
|
||||
'selected_project_ids': [],
|
||||
'selected_team_ids': [],
|
||||
}
|
||||
return render(request, 'core/index.html', context)
|
||||
|
||||
@ -2383,6 +2386,11 @@ def generate_report(request):
|
||||
# populate (same lists the Dashboard modal uses)
|
||||
context['projects'] = Project.objects.all().order_by('name')
|
||||
context['teams'] = Team.objects.all().order_by('name')
|
||||
# For the modal's <select multiple> pre-selection: stringify the IDs so
|
||||
# the template's `{% if p.id|stringformat:"s" in selected_project_ids %}`
|
||||
# comparison works (Django templates compare strings to strings).
|
||||
context['selected_project_ids'] = [str(p) for p in (project_ids or [])]
|
||||
context['selected_team_ids'] = [str(t) for t in (team_ids or [])]
|
||||
|
||||
return render(request, 'core/report.html', context)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user