feat: exporteren van vers-gegenereerde wachtwoorden als CSV (v0.4.30-beta)
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 38s

- "Exporteer als CSV"-knop toegevoegd aan het bestaande multireset-
  resultatenscherm (klas-wachtwoorden resetten in de School-navigator),
  naast de bestaande "kopieer alles"-knop.
- BELANGRIJKE BEPERKING, bewust zo: dit exporteert alleen wat op dit
  scherm al staat (net-gegenereerde wachtwoorden). Wachtwoorden worden
  na het zetten nergens leesbaar bewaard (alleen gehashet in de
  database) - er is dus geen "haal wachtwoorden van bestaande accounts
  op"-mogelijkheid en die komt er ook niet.
- CSV bevat gebruikersnaam (het echte inlogveld) naast de naam, ook al
  toont het scherm zelf alleen de naam - zonder gebruikersnaam is een
  uitdeelvel niet bruikbaar om mee in te loggen.
- Hergebruikt de csvValue()/downloadCsv()-helpers uit de vorige
  resultaten-exportfeature (v0.4.29-beta) - eerste echte tweede
  gebruiker, dus die keuze om ze lokaal in admin.js te houden i.p.v.
  te verplaatsen was terecht.
- Geverifieerd met de volledige testsuite (112/112) en een live
  browserdoorloop: klas-wachtwoorden resetten (dubbele bevestigingsklik)
  → CSV-download met correcte escaping van een leerlingnaam met komma
  én aanhalingsteken.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EPxzBVRXZZnBPvSAaPAbJ
This commit is contained in:
Ramon 2026-07-19 13:31:10 +02:00
parent 8fe6fc10cc
commit 4e4aeb4b6d
3 changed files with 20 additions and 2 deletions

View file

@ -1 +1 @@
0.4.29-beta 0.4.30-beta

View file

@ -615,6 +615,22 @@
copyAll.type = "button"; copyAll.type = "button";
copyAll.addEventListener("click", e=>{ e.preventDefault(); copyText(copyAll, all); }); copyAll.addEventListener("click", e=>{ e.preventDefault(); copyText(copyAll, all); });
box.appendChild(copyAll); box.appendChild(copyAll);
/* export als uitdeelvel - alleen mogelijk zolang dit scherm openstaat: de
wachtwoorden zijn hierna nergens meer in leesbare vorm te achterhalen
(alleen het gehashte wachtwoord blijft in de database), dus dit is
bewust "exporteer wat nu net gegenereerd is", niet "haal wachtwoorden
van bestaande accounts op". Gebruikersnaam (het echte inlog-veld) staat
er wél bij, ook al toont de schermlijst hierboven alleen de naam. */
const exportBtn = h("button","am-btn", T("amExportCsv"));
exportBtn.type = "button";
exportBtn.addEventListener("click", e=>{
e.preventDefault();
const header = [T("amExportColPupil"), T("amExportColUsername"), T("amResultPw")];
const rows = [header, ...resetResults.entries.map(en=>[en.displayName, en.username, en.password])];
const safeName = resetResults.title.replace(/[^a-z0-9]+/gi, "-");
downloadCsv(`${safeName}.csv`, rows);
});
box.appendChild(exportBtn);
const list = h("div","am-reset-list"); const list = h("div","am-reset-list");
resetResults.entries.forEach(en=>{ resetResults.entries.forEach(en=>{
const row = h("div","am-reset-row"); const row = h("div","am-reset-row");

View file

@ -2,7 +2,7 @@
"use strict"; "use strict";
/* version shown until /api/version resolves (or if the fetch fails, e.g. offline). /* version shown until /api/version resolves (or if the fetch fails, e.g. offline).
Kept in sync by hand with the VERSION file at the repo root on every release. */ Kept in sync by hand with the VERSION file at the repo root on every release. */
const VERSION = "0.4.29-beta"; const VERSION = "0.4.30-beta";
(function(){ (function(){
const tag = document.getElementById("verTag"); const tag = document.getElementById("verTag");
tag.textContent = "v"+VERSION; tag.textContent = "v"+VERSION;
@ -352,6 +352,7 @@ const I18N = {
amExportClass:"Exporteren per klas", amExportCsv:"Exporteer als CSV", amPickClassHint:"Kies eerst een klas.", amExportClass:"Exporteren per klas", amExportCsv:"Exporteer als CSV", amPickClassHint:"Kies eerst een klas.",
amExportColPupil:"Leerling", amExportColWidget:"Widget", amExportColAttempts:"Pogingen", amExportColPupil:"Leerling", amExportColWidget:"Widget", amExportColAttempts:"Pogingen",
amExportColCorrect:"Goed", amExportColStars:"Sterren", amExportColDate:"Datum", amExportColCorrect:"Goed", amExportColStars:"Sterren", amExportColDate:"Datum",
amExportColUsername:"Gebruikersnaam",
amExportDone:"Export gedownload ✓", amExportDone:"Export gedownload ✓",
amConfirmDel:"Weet je zeker dat je deze gebruiker wilt verwijderen?", amConfirmDel:"Weet je zeker dat je deze gebruiker wilt verwijderen?",
amCopy:"kopieer", amCopyAll:"kopieer alles", amCopy:"kopieer", amCopyAll:"kopieer alles",
@ -690,6 +691,7 @@ const I18N = {
amExportClass:"Export by class", amExportCsv:"Export as CSV", amPickClassHint:"Pick a class first.", amExportClass:"Export by class", amExportCsv:"Export as CSV", amPickClassHint:"Pick a class first.",
amExportColPupil:"Pupil", amExportColWidget:"Widget", amExportColAttempts:"Attempts", amExportColPupil:"Pupil", amExportColWidget:"Widget", amExportColAttempts:"Attempts",
amExportColCorrect:"Correct", amExportColStars:"Stars", amExportColDate:"Date", amExportColCorrect:"Correct", amExportColStars:"Stars", amExportColDate:"Date",
amExportColUsername:"Username",
amExportDone:"Export downloaded ✓", amExportDone:"Export downloaded ✓",
amConfirmDel:"Are you sure you want to delete this user?", amConfirmDel:"Are you sure you want to delete this user?",
amCopy:"copy", amCopyAll:"copy all", amCopy:"copy", amCopyAll:"copy all",