181 lines
7.8 KiB
HTML
181 lines
7.8 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Smartschool beheer{% endblock %}
|
||
{% block page_title %}Smartschool beheer{% endblock %}
|
||
{% block main_class %}medium{% endblock %}
|
||
|
||
{% block extra_css %}
|
||
<style>
|
||
#coAccountModal { z-index: 3000; }
|
||
#passwordModal { z-index: 4000; } /* reset-venster altijd bovenop de co-accountlijst */
|
||
</style>
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="card">
|
||
<div class="page-head"><h2>🏫 Wachtwoord & info</h2></div>
|
||
|
||
<form class="search-bar" method="POST" action="{{ url_for('/ss.smartschool') }}" onsubmit="showLoader()">
|
||
<input type="text" name="query" placeholder="Zoek op naam, voornaam, gebruikersnaam of internnummer..." value="{{ query or '' }}">
|
||
<button type="submit" class="btn-search">🔍 Zoeken</button>
|
||
</form>
|
||
|
||
{% if results %}
|
||
<div class="table-wrap">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Internnummer</th>
|
||
<th>Naam</th>
|
||
<th>Gebruikersnaam</th>
|
||
<th class="actions">Acties</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for user in results %}
|
||
<tr>
|
||
<td><strong>{{ user.internnummer }}</strong></td>
|
||
<td>{{ user.voornaam }} {{ user.naam }}</td>
|
||
<td>{{ user.gebruikersnaam }}</td>
|
||
<td class="actions">
|
||
<button type="button" class="btn-danger btn-sm" onclick="openResetModal('{{ user.internnummer }}', '{{ user.voornaam }} {{ user.naam }}', 0)">🔑 Reset WW</button>
|
||
<button type="button" class="btn-secondary btn-sm" onclick="viewCoAccounts('{{ user.gebruikersnaam }}')">👪 Co-accounts</button>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{% elif query %}
|
||
<p class="muted">Geen resultaten gevonden voor "{{ query }}".</p>
|
||
<p class="muted small">Op een deel van een naam zoekt PIVOT in de leerlingenlijst. Staat die nog leeg,
|
||
haal dan eerst de leerlingen op via Leerlingen › Informat & SS sync, of zoek op het volledige internnummer of de gebruikersnaam.</p>
|
||
{% endif %}
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block modals %}
|
||
<div id="passwordModal" class="modal-overlay">
|
||
<div class="modal-content">
|
||
<span class="close" onclick="closeModal('passwordModal')">×</span>
|
||
<h3>Wachtwoord reset</h3>
|
||
<p id="displayUser" style="font-weight:600; color: var(--primary-color);"></p>
|
||
<div class="field">
|
||
<label for="modalPasswordInput">Nieuw wachtwoord</label>
|
||
<div class="input-group">
|
||
<input type="text" id="modalPasswordInput" placeholder="Nieuw wachtwoord">
|
||
<button type="button" class="btn-light" title="Willekeurig genereren" onclick="generateRandomPass()">🎲</button>
|
||
</div>
|
||
</div>
|
||
<label class="check-box">
|
||
<input type="checkbox" id="pdfCheckbox"> PDF genereren voor deze persoon
|
||
</label>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn-ghost" onclick="closeModal('passwordModal')">Annuleren</button>
|
||
<button type="button" onclick="submitPasswordReset()">Bevestig reset</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="coAccountModal" class="modal-overlay">
|
||
<div class="modal-content wide">
|
||
<span class="close" onclick="closeModal('coAccountModal')">×</span>
|
||
<h3>Gekoppelde co-accounts</h3>
|
||
<div id="coAccountList"></div>
|
||
<div class="modal-footer">
|
||
<button type="button" onclick="closeModal('coAccountModal')">Sluiten</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block scripts %}
|
||
<script>
|
||
let currentTargetUser = "";
|
||
let currentResetType = 0;
|
||
let currentTargetName = "";
|
||
|
||
function closeModal(id) { document.getElementById(id).style.display = 'none'; }
|
||
|
||
function openResetModal(identifier, fullname, accType = 0) {
|
||
currentTargetUser = identifier;
|
||
currentResetType = accType;
|
||
currentTargetName = fullname;
|
||
document.getElementById('displayUser').innerText = fullname + (accType === 0 ? " (Leerling)" : " (Co-account)");
|
||
document.getElementById('modalPasswordInput').value = "";
|
||
document.getElementById('pdfCheckbox').checked = false;
|
||
document.getElementById('passwordModal').style.display = 'flex';
|
||
}
|
||
|
||
function generateRandomPass() {
|
||
const chars = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789";
|
||
let pass = "";
|
||
for (let i = 0; i < 10; i++) pass += chars.charAt(Math.floor(Math.random() * chars.length));
|
||
document.getElementById('modalPasswordInput').value = pass;
|
||
}
|
||
|
||
function submitPasswordReset() {
|
||
const newPass = document.getElementById('modalPasswordInput').value;
|
||
const genPdf = document.getElementById('pdfCheckbox').checked;
|
||
if (!newPass) return alert("Geen wachtwoord ingevuld!");
|
||
|
||
showLoader();
|
||
fetch("{{ url_for('/ss.smartschool_reset') }}", {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||
body: `username=${encodeURIComponent(currentTargetUser)}&new_password=${encodeURIComponent(newPass)}&account_type=${currentResetType}&generate_pdf=${genPdf}&display_name=${encodeURIComponent(currentTargetName)}`
|
||
})
|
||
.then(res => {
|
||
const contentType = res.headers.get("content-type");
|
||
if (contentType && contentType.includes("application/pdf")) {
|
||
return res.blob().then(blob => ({ type: 'pdf', data: blob }));
|
||
}
|
||
return res.json().then(data => ({ type: 'json', data: data }));
|
||
})
|
||
.then(result => {
|
||
hideLoader();
|
||
if (result.type === 'pdf') {
|
||
const url = window.URL.createObjectURL(result.data);
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = `Account_${currentTargetName}.pdf`;
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
closeModal('passwordModal');
|
||
} else if (result.data.status === "success") {
|
||
alert("Wachtwoord succesvol aangepast!");
|
||
closeModal('passwordModal');
|
||
} else {
|
||
alert("Fout: " + result.data.message);
|
||
}
|
||
}).catch(() => { hideLoader(); alert("Fout bij verbinding."); });
|
||
}
|
||
|
||
function viewCoAccounts(username) {
|
||
showLoader();
|
||
fetch("{{ url_for('/ss.smartschool_coaccounts') }}", {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||
body: `username=${encodeURIComponent(username)}`
|
||
})
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
hideLoader();
|
||
let html = '<div class="table-wrap"><table><thead><tr><th>Relatie</th><th>Naam</th><th class="actions">Actie</th></tr></thead><tbody>';
|
||
data.accounts.forEach(acc => {
|
||
const fullName = `${acc.voornaam} ${acc.naam}`;
|
||
html += `<tr>
|
||
<td>${acc.type}</td>
|
||
<td>${fullName}</td>
|
||
<td class="actions"><button type="button" class="btn-danger btn-sm" onclick="openResetModal('${acc.parent_internnummer}', '${fullName}', ${acc.index})">🔑 Reset</button></td>
|
||
</tr>`;
|
||
});
|
||
html += '</tbody></table></div>';
|
||
document.getElementById('coAccountList').innerHTML = html;
|
||
document.getElementById('coAccountModal').style.display = 'flex';
|
||
})
|
||
.catch(() => { hideLoader(); alert("Fout bij ophalen co-accounts."); });
|
||
}
|
||
</script>
|
||
{% endblock %}
|