202 lines
11 KiB
HTML
202 lines
11 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}{{ u.Gebruikersnaam }} – rechten{% endblock %}
|
||
{% block page_title %}Gebruiker: {{ u.Gebruikersnaam }}{% endblock %}
|
||
|
||
{% block extra_css %}
|
||
<style>
|
||
.terug { margin-bottom: 14px; display: inline-block; }
|
||
.rechten-layout { display: grid; grid-template-columns: minmax(240px, 320px) 1fr; gap: 20px; align-items: start; }
|
||
.scholen-paneel { border: 1px solid var(--border); border-radius: var(--radius-lg, 12px); overflow: hidden;
|
||
position: sticky; top: 12px; }
|
||
.scholen-paneel .zoek { padding: 10px; border-bottom: 1px solid var(--border); background: var(--surface-muted); }
|
||
.scholen-paneel .zoek input[type=search] { width: 100%; }
|
||
.scholen-paneel .zoek label { font-size: .85rem; margin-top: 8px; display: flex; gap: 6px; align-items: center; font-weight: 400; }
|
||
.scholen-lijst { list-style: none; margin: 0; padding: 0; max-height: 62vh; overflow-y: auto; }
|
||
.scholen-lijst a { display: flex; justify-content: space-between; gap: 8px; padding: 9px 12px; text-decoration: none;
|
||
color: inherit; border-bottom: 1px solid var(--border); font-size: .92rem; }
|
||
.scholen-lijst a:hover { background: var(--primary-light); }
|
||
.scholen-lijst a.actief { background: var(--primary-light); border-left: 3px solid var(--primary-color); font-weight: 700; }
|
||
.scholen-lijst a.leeg { color: var(--text-muted, #64748b); }
|
||
.scholen-lijst .teller { white-space: nowrap; font-size: .8rem; font-weight: 600; color: var(--primary-color); }
|
||
.scholen-lijst a.leeg .teller { color: var(--text-muted, #94a3b8); font-weight: 400; }
|
||
.scholen-lijst .geen { padding: 12px; color: var(--text-muted, #64748b); font-size: .9rem; }
|
||
.school-select { display: none; margin-bottom: 14px; }
|
||
|
||
.cat { border: 1px solid var(--border); border-radius: 10px; margin-bottom: 12px; }
|
||
.cat-kop { display: flex; justify-content: space-between; align-items: center; padding: 8px 12px;
|
||
background: var(--surface-muted); border-bottom: 1px solid var(--border); border-radius: 10px 10px 0 0; }
|
||
.cat-kop strong { color: var(--primary-color); font-size: .92rem; }
|
||
.cat-kop .knoppen button, .globaal button { padding: 2px 10px; font-size: 12px; }
|
||
.vinkjes { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 2px 16px; padding: 8px 12px; }
|
||
.vinkjes label { display: flex; gap: 8px; align-items: center; font-weight: 400; padding: 5px 0; cursor: pointer; margin: 0; }
|
||
.vinkjes input { width: 17px; height: 17px; flex: none; }
|
||
.globaal { display: flex; gap: 6px; align-items: center; }
|
||
|
||
details.ook { border: 1px dashed var(--border); border-radius: 10px; padding: 10px 12px; margin: 14px 0; }
|
||
details.ook summary { cursor: pointer; font-weight: 600; }
|
||
.ook-lijst { max-height: 260px; overflow-y: auto; margin-top: 8px; columns: 2 260px; }
|
||
.ook-lijst label { display: flex; gap: 8px; align-items: center; font-weight: 400; margin: 0; padding: 3px 0; break-inside: avoid; }
|
||
.ook-lijst input, details.ook .alle input { width: auto; }
|
||
|
||
@media (max-width: 760px) {
|
||
.rechten-layout { grid-template-columns: 1fr; }
|
||
.scholen-paneel { display: none; }
|
||
.school-select { display: block; }
|
||
}
|
||
</style>
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<a class="terug" href="{{ url_for('admin.settings') }}">← Alle gebruikers</a>
|
||
|
||
<div class="card">
|
||
<div class="page-head">
|
||
<h2>🔐 Rechten van {{ u.Gebruikersnaam }}</h2>
|
||
<a class="btn btn-sm btn-light" href="{{ url_for('admin.gebruiker', gid=u.Gebruiker_ID) }}">👤 Account</a>
|
||
</div>
|
||
|
||
{% if u.Veiligheidsgroep == ADMIN %}
|
||
<div class="alert alert-info">{{ u.Gebruikersnaam }} is <strong>administrator</strong> en heeft daardoor altijd alle rechten in alle scholen.
|
||
De vinkjes hieronder gelden pas als de rol ooit "Gebruiker" wordt.</div>
|
||
{% endif %}
|
||
|
||
{% if not scholen %}
|
||
<p class="muted">Je mag in geen enkele school rechten instellen.</p>
|
||
{% else %}
|
||
<div class="rechten-layout">
|
||
{# ---------- Scholen ---------- #}
|
||
<div class="scholen-paneel">
|
||
<div class="zoek">
|
||
<input type="search" id="zoekSchool" placeholder="🔍 Zoek school… ({{ scholen|length }})" oninput="filterScholen()">
|
||
<label><input type="checkbox" id="enkelMet" onchange="filterScholen()" style="width:auto"> Enkel scholen met rechten</label>
|
||
</div>
|
||
<ul class="scholen-lijst" id="scholenLijst">
|
||
{% for s in scholen %}
|
||
{% set n = aantallen.get(s.id, 0) %}
|
||
<li data-naam="{{ s.naam|lower }}" data-n="{{ n }}">
|
||
<a href="{{ url_for('admin.gebruiker_rechten', gid=u.Gebruiker_ID, school=s.id) }}"
|
||
class="{{ 'actief' if gekozen and s.id == gekozen.id else '' }} {{ 'leeg' if not n else '' }}">
|
||
<span>{{ s.naam }}{% if not s.actief %} <span class="badge badge-warning">inactief</span>{% endif %}</span>
|
||
<span class="teller">{{ n }}/{{ totaal }}</span>
|
||
</a>
|
||
</li>
|
||
{% endfor %}
|
||
<li class="geen" id="geenScholen" style="display:none">Geen scholen gevonden.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
{# ---------- Rechten van de gekozen school ---------- #}
|
||
<div>
|
||
<select class="school-select" onchange="location.href=this.value" aria-label="School">
|
||
{% for s in scholen %}
|
||
<option value="{{ url_for('admin.gebruiker_rechten', gid=u.Gebruiker_ID, school=s.id) }}"
|
||
{% if gekozen and s.id == gekozen.id %}selected{% endif %}>{{ s.naam }} ({{ aantallen.get(s.id, 0) }}/{{ totaal }})</option>
|
||
{% endfor %}
|
||
</select>
|
||
|
||
{% if gekozen %}
|
||
<form method="POST" action="{{ url_for('admin.gebruiker_rechten', gid=u.Gebruiker_ID) }}" id="rechtenForm"
|
||
onsubmit="return bevestig()">
|
||
<input type="hidden" name="school_id" value="{{ gekozen.id }}">
|
||
<div class="page-head" style="margin-bottom:10px">
|
||
<h3 style="margin:0">🏫 {{ gekozen.naam }}</h3>
|
||
<div class="globaal">
|
||
<span class="muted small" id="teller"></span>
|
||
<button type="button" class="btn-light" onclick="zet(null, true)">alles</button>
|
||
<button type="button" class="btn-light" onclick="zet(null, false)">niets</button>
|
||
</div>
|
||
</div>
|
||
<p class="muted small" style="margin-top:0">Zonder vinkje in deze school kan {{ u.Gebruikersnaam }} er niet inloggen.</p>
|
||
|
||
{% for cat, items in categorieen.items() %}
|
||
<div class="cat">
|
||
<div class="cat-kop">
|
||
<strong>{{ cat }}</strong>
|
||
<span class="knoppen">
|
||
<button type="button" class="btn-light" onclick="zet('{{ loop.index }}', true)">alles</button>
|
||
<button type="button" class="btn-light" onclick="zet('{{ loop.index }}', false)">niets</button>
|
||
</span>
|
||
</div>
|
||
<div class="vinkjes">
|
||
{% set ci = loop.index %}
|
||
{% for code, naam in items %}
|
||
<label><input type="checkbox" name="r|{{ code }}" value="1" data-cat="{{ ci }}" onchange="tel()"
|
||
{% if code in huidig %}checked{% endif %}> {{ naam }}</label>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
|
||
{% if scholen|length > 1 %}
|
||
<details class="ook">
|
||
<summary>📋 Deze rechten ook toepassen op andere scholen…</summary>
|
||
<p class="field-hint">De aangevinkte scholen krijgen exact dezelfde rechten als {{ gekozen.naam }}. Wat {{ u.Gebruikersnaam }} daar nu mag, wordt overschreven.</p>
|
||
<label class="alle" style="font-weight:600;display:flex;gap:8px;align-items:center">
|
||
<input type="checkbox" name="ook_alle" value="1" id="ookAlle" onchange="ookAlleWissel()"> Alle {{ scholen|length }} scholen</label>
|
||
<input type="search" placeholder="🔍 Zoek school…" oninput="filterOok(this.value)" style="margin-top:8px">
|
||
<div class="ook-lijst" id="ookLijst">
|
||
{% for s in scholen if s.id != gekozen.id %}
|
||
<label data-naam="{{ s.naam|lower }}"><input type="checkbox" name="ook" value="{{ s.id }}"> {{ s.naam }}
|
||
<span class="muted small">({{ aantallen.get(s.id, 0) }})</span></label>
|
||
{% endfor %}
|
||
</div>
|
||
</details>
|
||
{% endif %}
|
||
|
||
<button type="submit" class="btn-success">💾 Rechten opslaan</button>
|
||
</form>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block scripts %}
|
||
<script>
|
||
function vinkjes(cat) {
|
||
var sel = '#rechtenForm .vinkjes input' + (cat ? '[data-cat="' + cat + '"]' : '');
|
||
return document.querySelectorAll(sel);
|
||
}
|
||
function zet(cat, aan) { vinkjes(cat).forEach(function (cb) { cb.checked = aan; }); tel(); }
|
||
function tel() {
|
||
var t = document.getElementById('teller'); if (!t) return;
|
||
var alle = vinkjes(null), n = 0;
|
||
alle.forEach(function (cb) { if (cb.checked) n++; });
|
||
t.textContent = n + ' van ' + alle.length + ' aangevinkt';
|
||
}
|
||
function filterScholen() {
|
||
var q = document.getElementById('zoekSchool').value.trim().toLowerCase();
|
||
var enkel = document.getElementById('enkelMet').checked, zichtbaar = 0;
|
||
document.querySelectorAll('#scholenLijst li[data-naam]').forEach(function (li) {
|
||
var ok = li.dataset.naam.indexOf(q) !== -1 && (!enkel || li.dataset.n !== '0');
|
||
li.style.display = ok ? '' : 'none'; if (ok) zichtbaar++;
|
||
});
|
||
document.getElementById('geenScholen').style.display = zichtbaar ? 'none' : '';
|
||
}
|
||
function filterOok(q) {
|
||
q = q.trim().toLowerCase();
|
||
document.querySelectorAll('#ookLijst label').forEach(function (l) {
|
||
l.style.display = l.dataset.naam.indexOf(q) !== -1 ? '' : 'none';
|
||
});
|
||
}
|
||
function ookAlleWissel() {
|
||
var aan = document.getElementById('ookAlle').checked;
|
||
document.querySelectorAll('#ookLijst input').forEach(function (cb) { cb.checked = aan; cb.disabled = aan; });
|
||
}
|
||
function bevestig() {
|
||
var alle = document.getElementById('ookAlle');
|
||
var n = (alle && alle.checked) ? {{ scholen|length - 1 }} : document.querySelectorAll('#ookLijst input:checked').length;
|
||
if (!n) { if (typeof showLoader === 'function') showLoader(); return true; }
|
||
var ok = confirm('Dezelfde rechten ook instellen in ' + n + ' andere school/scholen? Wat daar nu aangevinkt is, wordt overschreven.');
|
||
if (ok && typeof showLoader === 'function') showLoader();
|
||
return ok;
|
||
}
|
||
tel();
|
||
// gekozen school in beeld scrollen
|
||
var actief = document.querySelector('#scholenLijst a.actief');
|
||
if (actief) { var l = document.getElementById('scholenLijst'); l.scrollTop = actief.parentNode.offsetTop - l.clientHeight / 2; }
|
||
</script>
|
||
{% endblock %}
|