v0.3.35-beta: schollenlijst in Systeem + verborgen formulieren + gelijke maten
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 32s

- Systeem-tabblad toont nu een overzicht van alle scholen als volwaardige
  rijen met een bevestigde verwijder-actie
- Het school-toevoegen-formulier zit achter een "+ School"-knop (zelfde
  patroon als gebruikers) en houdt de naam-bevestiging; de uitlegtekst is
  weg - teksten kort en krachtig
- Alle formulieren en knoppen in het beheer op dezelfde controlhoogte;
  fix: de rij-flexregels van invoervelden drukten velden binnen een
  veldlabel (kolom-flex) verticaal plat
- Ontbrekende veldlabel-tekst "Naam" toegevoegd (nl/en)
This commit is contained in:
Ramon 2026-07-15 15:53:10 +02:00
parent 03b8e6a41b
commit b2ca4f93d5
4 changed files with 59 additions and 23 deletions

View file

@ -1 +1 @@
0.3.34-beta 0.3.35-beta

View file

@ -1164,13 +1164,27 @@
} }
.am-edit:hover{opacity:1; background:var(--surface-3);} .am-edit:hover{opacity:1; background:var(--surface-3);}
.am-edit.on{opacity:1; background:var(--accent-soft);} .am-edit.on{opacity:1; background:var(--accent-soft);}
/* uniforme maat: álle knoppen en velden in het beheer op controlhoogte,
zodat formulieren en actieknoppen in elke rij gelijk uitlijnen */
#adminModal .tbtn{
min-height:var(--control-h); height:var(--control-h);
padding:0 14px; font-size:14px;
}
/* één interactiesysteem: mini-label boven elk veld/select/knopgroep */ /* één interactiesysteem: mini-label boven elk veld/select/knopgroep */
.am-field{display:flex; flex-direction:column; gap:3px;} .am-field{display:flex; flex-direction:column; gap:3px; min-width:0;}
.am-field-lbl{ .am-field-lbl{
font-size:10.5px; font-weight:800; color:var(--muted); font-size:10.5px; font-weight:800; color:var(--muted);
text-transform:uppercase; letter-spacing:.4px; text-transform:uppercase; letter-spacing:.4px;
} }
/* de rij-flexregels van .am-inp (flex-basis 0/100%) gelden binnen de
kolom-flex van het label verticaal en drukten het veld plat - binnenin
een veldlabel dus altijd de vaste controlhoogte, breedte via het label */
.am-field > .am-inp, .am-field > .am-sel, .am-field > .am-pw, .am-field > .am-inline,
.am-field > .am-classes, .am-field > .am-actions{flex:none; width:100%;}
.am-add .am-field{flex:1 1 100%;}
.am-row-tools .am-field{flex:0 1 auto; min-width:150px;}
.am-inline{display:flex; gap:6px; align-items:center;} .am-inline{display:flex; gap:6px; align-items:center;}
.am-inline > .am-inp, .am-inline > .am-pw{flex:1 1 auto; min-width:0;}
/* gevaarlijke acties: afwijkende kleur + tweede klik als bevestiging */ /* gevaarlijke acties: afwijkende kleur + tweede klik als bevestiging */
.am-btn.am-danger{background:var(--red-soft); color:var(--red); font-weight:800;} .am-btn.am-danger{background:var(--red-soft); color:var(--red); font-weight:800;}
.am-btn.am-danger.armed{background:var(--red); color:#fff;} .am-btn.am-danger.armed{background:var(--red); color:#fff;}

View file

@ -419,21 +419,40 @@
return box; return box;
} }
/* systeem: nieuwe school + systeemmanagers beheren. Dit tabblad is waar een /* systeem: overzicht van alle scholen + nieuwe school + systeemmanagers.
super zaken regelt die niet aan één school vastzitten; de schoolkiezer- De schoolkiezer-contextbalk is hier verborgen (zie switchAdminTab), want
contextbalk wordt hier juist verborgen (zie switchAdminTab), want niets niets op dit tabblad hangt van een gekozen school af. Toevoegen zit
op dit tabblad hangt van een gekozen school af. Een school aanmaken is achter een bewuste extra stap (-knop klapt het formulier uit, zoals
bewust een twee-staps-actie: de knop wordt pas actief bij een echte naam bij gebruikers) en bevestigt daarna nog met de naam erin. */
en vraagt daarna een bevestigende tweede klik (typefout-bescherming). */
function renderScholenPanel(panel){ function renderScholenPanel(panel){
panel.appendChild(h("div","am-h3", T("amNewSchool"))); const list = h("div","am-list");
panel.appendChild(h("div","guestnote", T("amNewSchoolDesc"))); SCHOOLS.forEach(s=>{
const bar = h("div","am-add"); const row = h("div","am-row");
row.appendChild(h("span","am-name", s.name));
const acts = h("div","am-actions");
acts.appendChild(dangerBtn("🗑 " + T("amDelete"), "amDeleteSchoolWarn", async ()=>{
try{
await api("/admin/schools/"+s.id, {method:"DELETE"});
if(String(selSchool)===String(s.id)) selSchool = "";
reload();
}catch(e){ msg(e.message); }
}));
row.appendChild(acts);
list.appendChild(row);
});
panel.appendChild(list);
const wrap = h("div","am-add-wrap");
const toggle = h("button","tbtn ghost", T("amNewSchool"));
toggle.type = "button";
wrap.appendChild(toggle);
const f = h("div","am-add");
f.style.display = "none";
const inp = h("input","am-inp"); const inp = h("input","am-inp");
inp.placeholder = T("amSchoolNamePh"); inp.placeholder = T("amSchoolNamePh");
inp.maxLength = 80; inp.maxLength = 80;
inp.addEventListener("keydown", ev=>ev.stopPropagation()); inp.addEventListener("keydown", ev=>ev.stopPropagation());
bar.appendChild(field("amFieldName", inp)); f.appendChild(field("amFieldName", inp));
const add = h("button","tbtn", T("amNewSchool")); const add = h("button","tbtn", T("amNewSchool"));
add.type = "button"; add.type = "button";
add.disabled = true; add.disabled = true;
@ -456,16 +475,19 @@
reload(); reload();
}catch(e){ msg(e.message); } }catch(e){ msg(e.message); }
}); });
bar.appendChild(add); f.appendChild(add);
panel.appendChild(bar); wrap.appendChild(f);
toggle.addEventListener("click", ()=>{
toggle.style.display = "none";
f.style.display = "flex";
inp.focus();
});
panel.appendChild(wrap);
/* systeemmanagers horen niet bij één school, dus het aanmaken ervan /* systeemmanagers horen niet bij één school, dus het aanmaken ervan
staat hier i.p.v. tussen de school-gebonden gebruikers in de Gebruikers-tab staat hier i.p.v. tussen de school-gebonden gebruikers in de Gebruikers-tab
(de lijst van bestaande supers blijft wel gewoon in Gebruikers staan) */ (de lijst van bestaande supers blijft wel gewoon in Gebruikers staan) */
if(creatableRoles().includes("super")){ if(creatableRoles().includes("super")) panel.appendChild(addForm("super"));
panel.appendChild(h("div","am-h3", T("roleSuper")));
panel.appendChild(addForm("super"));
}
} }
/* klassen (admin/super binnen een school) */ /* klassen (admin/super binnen een school) */

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.3.34-beta"; const VERSION = "0.3.35-beta";
(function(){ (function(){
const tag = document.getElementById("verTag"); const tag = document.getElementById("verTag");
tag.textContent = "v"+VERSION; tag.textContent = "v"+VERSION;
@ -184,14 +184,14 @@ const I18N = {
amPickSchoolHint:"Kies hierboven eerst een school (🏫).", amPickSchool:"Kies een school", amPickSchoolHint:"Kies hierboven eerst een school (🏫).", amPickSchool:"Kies een school",
amPupils:"Leerlingen", amPupilOne:"Leerling", amEdit:"Bewerken", amPupils:"Leerlingen", amPupilOne:"Leerling", amEdit:"Bewerken",
amSure:"weet je het zeker?", amDelete:"verwijder", amSure:"weet je het zeker?", amDelete:"verwijder",
amFieldRole:"Functie", amFieldExtraRoles:"Extra functies", amFieldClass:"Klas", amFieldName:"Naam", amFieldRole:"Functie", amFieldExtraRoles:"Extra functies", amFieldClass:"Klas",
amFieldPw:"Wachtwoord", amFieldActions:"Acties", amPwTypePh:"typ een wachtwoord…", amFieldPw:"Wachtwoord", amFieldActions:"Acties", amPwTypePh:"typ een wachtwoord…",
amNewPwWarn:"Maakt een nieuw wachtwoord aan. Het oude wachtwoord werkt daarna niet meer en de gebruiker wordt overal uitgelogd.", amNewPwWarn:"Maakt een nieuw wachtwoord aan. Het oude wachtwoord werkt daarna niet meer en de gebruiker wordt overal uitgelogd.",
amNewCodeWarn:"Maakt een nieuwe koppelcode aan. Het huidige wachtwoord vervalt direct; de gebruiker moet opnieuw activeren.", amNewCodeWarn:"Maakt een nieuwe koppelcode aan. Het huidige wachtwoord vervalt direct; de gebruiker moet opnieuw activeren.",
amDeleteWarn:"Verwijdert dit account definitief, inclusief borden en woorden.", amDeleteWarn:"Verwijdert dit account definitief, inclusief borden en woorden.",
amResultPw:"Nieuw wachtwoord", amResultCode:"Nieuwe koppelcode", amResultPw:"Nieuw wachtwoord", amResultCode:"Nieuwe koppelcode",
amNewSchoolDesc:"De schoolnaam verschijnt op het inlogscherm voor alle gebruikers van die school. Kies de definitieve naam - hernoemen kan later niet via dit scherm.",
amSchoolNamePh:"naam van de school…", amNewSchoolConfirm:"Aanmaken:", amSchoolNamePh:"naam van de school…", amNewSchoolConfirm:"Aanmaken:",
amDeleteSchoolWarn:"Verwijdert deze school met alle klassen en gebruikers. Dit kan niet ongedaan worden gemaakt.",
amClassNamePh:"naam van de klas…", amClassNamePh:"naam van de klas…",
amDeleteClassWarn:"Verwijdert deze klas; leerlingen blijven bestaan maar staan daarna zonder klas.", amDeleteClassWarn:"Verwijdert deze klas; leerlingen blijven bestaan maar staan daarna zonder klas.",
amNewSchool:" School", amNewClass:" Klas", amNewTeacher:" Groepsleiding", amNewSchool:" School", amNewClass:" Klas", amNewTeacher:" Groepsleiding",
@ -380,14 +380,14 @@ const I18N = {
amPickSchoolHint:"First pick a school above (🏫).", amPickSchool:"Pick a school", amPickSchoolHint:"First pick a school above (🏫).", amPickSchool:"Pick a school",
amPupils:"Pupils", amPupilOne:"Pupil", amEdit:"Edit", amPupils:"Pupils", amPupilOne:"Pupil", amEdit:"Edit",
amSure:"are you sure?", amDelete:"delete", amSure:"are you sure?", amDelete:"delete",
amFieldRole:"Role", amFieldExtraRoles:"Extra roles", amFieldClass:"Class", amFieldName:"Name", amFieldRole:"Role", amFieldExtraRoles:"Extra roles", amFieldClass:"Class",
amFieldPw:"Password", amFieldActions:"Actions", amPwTypePh:"type a password…", amFieldPw:"Password", amFieldActions:"Actions", amPwTypePh:"type a password…",
amNewPwWarn:"Generates a new password. The old one stops working and the user is signed out everywhere.", amNewPwWarn:"Generates a new password. The old one stops working and the user is signed out everywhere.",
amNewCodeWarn:"Generates a new link code. The current password stops working immediately; the user must re-activate.", amNewCodeWarn:"Generates a new link code. The current password stops working immediately; the user must re-activate.",
amDeleteWarn:"Deletes this account permanently, including boards and words.", amDeleteWarn:"Deletes this account permanently, including boards and words.",
amResultPw:"New password", amResultCode:"New link code", amResultPw:"New password", amResultCode:"New link code",
amNewSchoolDesc:"The school name appears on the login screen for all users of that school. Pick the final name - it cannot be renamed from this screen later.",
amSchoolNamePh:"name of the school…", amNewSchoolConfirm:"Create:", amSchoolNamePh:"name of the school…", amNewSchoolConfirm:"Create:",
amDeleteSchoolWarn:"Deletes this school with all its classes and users. This cannot be undone.",
amClassNamePh:"name of the class…", amClassNamePh:"name of the class…",
amDeleteClassWarn:"Deletes this class; pupils remain but end up without a class.", amDeleteClassWarn:"Deletes this class; pupils remain but end up without a class.",
amNewSchool:" School", amNewClass:" Class", amNewTeacher:" Group leader", amNewSchool:" School", amNewClass:" Class", amNewTeacher:" Group leader",