Files
Pivot/templates/ipblokkade_school.html
T
2026-10-14 13:34:37 +02:00

144 lines
7.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}Toegestane IP-adressen{% endblock %}
{% block page_title %}Toegestane IP-adressen{% endblock %}
{% block extra_css %}
<style>
.ip-form { display: flex; flex-wrap: wrap; gap: 10px; align-items: end; }
.ip-form .field { margin: 0; flex: 0 1 340px; }
.mijn-ip { display: inline-flex; gap: 8px; align-items: center; padding: 6px 12px; border-radius: 999px;
background: var(--surface-muted); border: 1px solid var(--border); font-size: .92em; }
.mijn-ip button { all: unset; cursor: pointer; color: var(--primary-color); font-size: .9em; }
.mono, td.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.tabel-zoek { margin-bottom: 10px; max-width: 360px; }
th.sorteer { cursor: pointer; user-select: none; white-space: nowrap; }
th.sorteer:hover { color: var(--primary-color); }
th.sorteer .pijl::after { content: "↕"; opacity: .35; margin-left: 2px; }
th.sorteer.op .pijl::after { content: "▲"; opacity: 1; }
th.sorteer.af .pijl::after { content: "▼"; opacity: 1; }
.tabel-voet { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 10px; margin-top: 12px; }
.paginering { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
</style>
{% endblock %}
{% block content %}
<div class="card">
<div class="page-head">
<h2>✅ Toegestane IP-adressen · {{ school_naam }}</h2>
<span class="mijn-ip">Jouw IP-adres: <strong class="mono">{{ mijn_ip }}</strong>
{% if not lokaal %}<button type="button" id="gebruikMijnIp" title="Invullen in het veld hieronder">invullen</button>{% endif %}</span>
</div>
<p class="field-hint" style="margin-top:-6px">Een adres in deze lijst mag PIVOT altijd openen. Je voegt het toe voor
{{ school_naam }}, met jouw naam ({{ naam }}) als opmerking. Je kan enkel de adressen verwijderen die je zelf toegevoegd hebt.</p>
<form method="POST" action="{{ url_for('ipblokkade.toevoegen') }}" class="ip-form">
<div class="field">
<label for="reeks">IP-adres</label>
<input type="text" id="reeks" name="reeks" required class="mono" placeholder="bv. 85.12.3.4" autocomplete="off">
</div>
<button type="submit">➕ Toevoegen</button>
</form>
</div>
<div class="card ip-tabel" data-sleutel="school">
<h2 class="card-title">Lijst <span class="muted small">({{ rijen|length }})</span></h2>
{% if rijen|length > 10 %}<input type="search" class="tabel-zoek" placeholder="Zoek een adres of naam..." aria-label="Zoeken">{% endif %}
<div class="table-wrap">
<table>
<thead>
<tr>
<th class="sorteer" data-tekst>IP-adres <span class="pijl"></span></th>
<th class="sorteer" data-tekst>Opmerking <span class="pijl"></span></th>
<th class="sorteer">Toegevoegd <span class="pijl"></span></th>
<th class="actions"></th>
</tr>
</thead>
<tbody>
{% for r in rijen %}
<tr>
<td class="mono" data-sort="{{ r.Sorteer }}"><strong>{{ r.Reeks }}</strong></td>
<td data-sort="{{ r.Opmerking or '' }}">{{ r.Opmerking or '' }}</td>
<td class="muted small" data-sort="{{ r.Aangemaakt.isoformat() }}">{{ r.Aangemaakt.strftime('%d-%m-%Y %H:%M') }}</td>
<td class="actions">
{% if r.Eigen %}
<form method="POST" action="{{ url_for('ipblokkade.verwijderen', regel_id=r.ID) }}" style="margin:0"
onsubmit="return confirm({{ (r.Reeks ~ ' uit de lijst verwijderen?')|tojson|forceescape }})">
<button type="submit" class="btn-sm btn-ghost">🗑️ Verwijderen</button>
</form>
{% endif %}
</td>
</tr>
{% else %}
<tr class="empty-row"><td colspan="4">Er zijn nog geen toegestane adressen voor {{ school_naam }}.</td></tr>
{% endfor %}
</tbody>
</table>
</div>
{% if rijen %}
<div class="tabel-voet">
<div style="display:flex;align-items:center;gap:14px;flex-wrap:wrap">
<div class="muted small teller"></div>
<span class="per-pagina-plek"></span>
</div>
<nav class="paginering" aria-label="Pagina's"></nav>
</div>
{% endif %}
</div>
{% endblock %}
{% block scripts %}
<script>
document.getElementById('gebruikMijnIp')?.addEventListener('click', () => {
const v = document.getElementById('reeks'); v.value = {{ mijn_ip|tojson }}; v.focus();
});
document.querySelectorAll('.ip-tabel').forEach(kaart => {
const body = kaart.querySelector('tbody');
if (!body || body.querySelector('.empty-row')) return;
const sleutel = 'ip-' + kaart.dataset.sleutel;
let PER_PAGINA = perPagina(sleutel), pagina = 1, zoek = '';
const zoekveld = kaart.querySelector('.tabel-zoek');
function toon() {
const rijen = Array.from(body.rows).filter(tr => !zoek || tr.textContent.toLowerCase().includes(zoek));
const grootte = PER_PAGINA || Infinity, paginas = Math.max(1, Math.ceil(rijen.length / grootte));
pagina = Math.min(Math.max(1, pagina), paginas);
const van = PER_PAGINA ? (pagina - 1) * PER_PAGINA : 0, tot = van + grootte;
Array.from(body.rows).forEach(tr => tr.style.display = 'none');
rijen.forEach((tr, i) => tr.style.display = (i >= van && i < tot) ? '' : 'none');
kaart.querySelector('.teller').textContent = rijen.length
? `${van + 1}–${Math.min(tot, rijen.length)} van ${rijen.length}` : 'Niets gevonden';
const nav = kaart.querySelector('.paginering');
nav.innerHTML = '';
if (paginas <= 1) return;
const knop = (label, p, actief) => {
const b = document.createElement('button');
b.type = 'button'; b.textContent = label; b.className = 'btn-sm ' + (actief ? 'btn-secondary' : 'btn-light');
b.onclick = () => { pagina = p; toon(); };
nav.appendChild(b);
};
if (pagina > 1) { knop('«', 1); knop('‹ Vorige', pagina - 1); }
for (let p = Math.max(1, pagina - 2); p <= Math.min(paginas, pagina + 2); p++) knop(String(p), p, p === pagina);
if (pagina < paginas) { knop('Volgende ›', pagina + 1); knop('»', paginas); }
}
if (zoekveld) zoekveld.addEventListener('input', () => { zoek = zoekveld.value.trim().toLowerCase(); pagina = 1; toon(); });
let kol = null, op = true;
kaart.querySelectorAll('th.sorteer').forEach(th => th.addEventListener('click', () => {
const k = th.cellIndex;
op = kol === k ? !op : 'tekst' in th.dataset;
kol = k;
kaart.querySelectorAll('th.sorteer').forEach(x => x.classList.remove('op', 'af'));
th.classList.add(op ? 'op' : 'af');
Array.from(body.rows).sort((a, b) => {
const x = a.cells[k].dataset.sort || '', y = b.cells[k].dataset.sort || '';
if (!x !== !y) return x ? -1 : 1;
const c = x.localeCompare(y, 'nl', { numeric: true, sensitivity: 'base' });
return op ? c : -c;
}).forEach(tr => body.appendChild(tr));
pagina = 1; toon();
}));
perPaginaKiezer(kaart.querySelector('.per-pagina-plek'), sleutel, n => { PER_PAGINA = n; pagina = 1; toon(); });
toon();
});
</script>
{% endblock %}