Voeg thematische kleurplaten en creatieve niveaus toe (v0.4.65-beta) #3

Open
bes-r wants to merge 207 commits from bes-r/kleurplaten-v0-4-65 into main AGit
3 changed files with 57 additions and 53 deletions
Showing only changes of commit 30818dc5f2 - Show all commits

View file

@ -1 +1 @@
0.3.93-beta
0.3.94-beta

View file

@ -359,7 +359,8 @@
/* het bewerkformulier van één gebruiker; wordt gebruikt door het
detailpaneel (gebruikers) én inline door het Systeem-tabblad (subrijen) */
function userTools(u){
function userTools(u, note){
note = note || msg;
const tools = h("div","am-tools");
const actions = h("div","am-actions");
const isStaff = ["teacher","admin","super"].includes(u.role);
@ -373,7 +374,7 @@
ss.value = u.schoolId ?? "";
ss.addEventListener("change", async ()=>{
try{ await api("/admin/users/"+u.id, {method:"PATCH", body:{ schoolId: ss.value ? +ss.value : null }}); reload(); }
catch(e){ msg(e.message); ss.value = u.schoolId ?? ""; }
catch(e){ note(e.message); ss.value = u.schoolId ?? ""; }
});
tools.appendChild(field("amFieldSchool", ss));
}
@ -385,7 +386,7 @@
rs.value = u.role;
rs.addEventListener("change", async ()=>{
try{ await api("/admin/users/"+u.id, {method:"PATCH", body:{role: rs.value}}); reload(); }
catch(e){ msg(e.message); }
catch(e){ note(e.message); }
});
tools.appendChild(field("amFieldRole", rs));
}
@ -403,7 +404,7 @@
x.title = T("amClassRemove");
x.addEventListener("click", async ()=>{
try{ await api("/admin/classes/"+cid+"/teachers", {body:{ userId: u.id, remove:true }}); reload(); }
catch(e){ msg(e.message); }
catch(e){ note(e.message); }
});
chip.appendChild(x);
wrap.appendChild(chip);
@ -416,7 +417,7 @@
addSel.addEventListener("change", async ()=>{
if(!addSel.value) return;
try{ await api("/admin/classes/"+addSel.value+"/teachers", {body:{ userId: u.id }}); reload(); }
catch(e){ msg(e.message); }
catch(e){ note(e.message); }
});
wrap.appendChild(addSel);
}
@ -427,7 +428,7 @@
const cs = classSel(u.classId);
cs.addEventListener("change", async ()=>{
try{ await api("/admin/users/"+u.id, {method:"PATCH", body:{classId: cs.value ? +cs.value : null}}); }
catch(e){ msg(e.message); }
catch(e){ note(e.message); }
});
tools.appendChild(field("amFieldClass", cs));
/* wachtwoord inzien en aanpassen - alleen zichtbaar zolang de leerling
@ -440,7 +441,7 @@
pw.addEventListener("change", async ()=>{
if(pw.value.length < 4) return;
try{ await api("/admin/users/"+u.id, {method:"PATCH", body:{password: pw.value}}); reload(); }
catch(e){ msg(e.message); }
catch(e){ note(e.message); }
});
pwWrap.appendChild(pw);
const pwCopy = h("button","am-btn", T("amCopy"));
@ -456,7 +457,7 @@
rowResults.set(u.id, { label: T("amResultPw"), value: password });
selectedUserKey = "u:"+u.id;
reload();
}catch(e){ msg(e.message); }
}catch(e){ note(e.message); }
}));
}
/* eenmalige ouder-code waarmee een ouder dit kind aan het eigen
@ -467,7 +468,7 @@
rowResults.set(u.id, { label: T("amResultParentCode"), value: r.parentCode });
selectedUserKey = "u:"+u.id;
reload();
}catch(e){ msg(e.message); }
}catch(e){ note(e.message); }
}));
}else{
if(u.pending && u.linkCode){
@ -480,7 +481,7 @@
rowResults.set(u.id, { label: T("amResultCode"), value: r.linkCode });
selectedUserKey = "u:"+u.id;
reload();
}catch(e){ msg(e.message); }
}catch(e){ note(e.message); }
}));
/* direct een nieuw wachtwoord zetten, zonder de koppelcode-activatie */
actions.appendChild(dangerBtn(T("amNewPw"), "amNewPwWarn", async ()=>{
@ -489,14 +490,14 @@
rowResults.set(u.id, { label: T("amResultPw"), value: r.password });
selectedUserKey = "u:"+u.id;
reload();
}catch(e){ msg(e.message); }
}catch(e){ note(e.message); }
}));
}
}
if(u.id !== currentUser.id){
const del = dangerBtn(T("amDelete"), "amDeleteWarn", async ()=>{
try{ await api("/admin/users/"+u.id, {method:"DELETE"}); selectedUserKey = null; reload(); }
catch(e){ msg(e.message); }
catch(e){ note(e.message); }
});
actions.appendChild(del);
}
@ -580,7 +581,11 @@
detailHost.appendChild(detailHead(u.displayName, T(roleKey(u.role)) + (u.displayName!==u.username ? ` · ${u.username}` : "")));
const badge = resultBadge(u);
if(badge) detailHost.appendChild(badge);
detailHost.appendChild(userTools(u));
/* fouten (bv. verwijderen mislukt) tonen we hier, waar de beheerder kijkt,
niet alleen bovenaan het paneel (daar valt het buiten beeld) */
const note = h("div","am-detail-msg formMsg");
detailHost.appendChild(note);
detailHost.appendChild(userTools(u, (t)=>{ note.textContent = t || ""; }));
return;
}
if(selectedUserKey && selectedUserKey.startsWith("req:")){
@ -1297,25 +1302,10 @@
master.appendChild(thead);
const list = h("div","am-list am-userlist");
/* losse accounts (ooit aan een school gekoppeld, nu zonder): alleen
relevant voor de systeemmanager in de alle-scholen-weergave */
const showLoose = currentUser.role==="super" && !selSchool;
const isLoose = u=>showLoose && ["teacher","admin","pupil"].includes(u.role) && u.schoolId==null;
const staffGroups = [["super", T("amSuperGroup")], ["admin", T("roleAdmin")], ["teacher", T("roleTeacher")]];
staffGroups.forEach(([role, label])=>{
const us = USERS.filter(u=>u.role===role && !isLoose(u));
if(!us.length) return;
list.appendChild(h("div","am-group", `${label} (${us.length})`));
us.forEach(u=>list.appendChild(userCells(u)));
});
const pupils = USERS.filter(u=>u.role==="pupil" && !isLoose(u));
const schoolChosen = schoolChosenTop;
/* leerlingen staan onder inklapbare groepskoppen (standaard dicht): zo
blijft de lijst overzichtelijk bij grote scholen; zoeken kijkt altijd
door alle groepen heen (zie applyUserFilter) */
const pupilGroup = (key, label, us)=>{
/* inklapbare groepskop; standaard dicht tenzij defaultOpen (dan onthoudt
closedGroups een bewuste dichtklap). Zoeken kijkt door alle groepen heen. */
const group = (key, label, us, defaultOpen)=>{
if(defaultOpen && !closedGroups.has(key)) openGroups.add(key);
const g = h("div","am-group am-group-toggle");
g.dataset.collapsible = "1";
g.dataset.gkey = key;
@ -1331,27 +1321,41 @@
us.forEach(u=>list.appendChild(userCells(u)));
};
/* per-klas indeling heeft alleen zin met één gekozen school (CLASSES is dan
betrouwbaar); zonder gekozen school (super, alle scholen) of voor groepsleiding
één groep - anders vallen leerlingen met een classId die niet in
de (dan lege) CLASSES-lijst voorkomt onterecht helemaal weg */
if(currentUser.role==="teacher" || !schoolChosen){
if(pupils.length) pupilGroup("pupils", T("amPupils"), pupils);
}else{
CLASSES.forEach(c=>{
const us = pupils.filter(u=>u.classId===c.id);
/* met een gekozen school staan de klasgroepen standaard open - de
schoolkeuze wás al het filter; dichtklappen wordt onthouden */
if(us.length && !closedGroups.has("class:"+c.id)) openGroups.add("class:"+c.id);
if(us.length) pupilGroup("class:"+c.id, c.name, us);
if(currentUser.role==="super" && !selSchool){
/* ALLE SCHOLEN: groepeer per school zodat je meteen ziet wie waar hoort;
daarna systeemmanagers, ouders en losse accounts apart */
const roleOrder = { admin:0, teacher:1, pupil:2 };
SCHOOLS.forEach(sc=>{
const us = USERS.filter(u=>Number(u.schoolId)===Number(sc.id))
.sort((a,b)=>(roleOrder[a.role]??9)-(roleOrder[b.role]??9) || a.displayName.localeCompare(b.displayName));
if(us.length) group("gschool:"+sc.id, sc.name, us);
});
const noClass = pupils.filter(u=>!u.classId);
if(noClass.length) pupilGroup("class:none", T("amNoClass"), noClass);
const supers = USERS.filter(u=>u.role==="super");
if(supers.length) group("gsys", T("amSuperGroup"), supers);
const parents = USERS.filter(u=>u.role==="parent");
if(parents.length) group("gparents", T("amParents"), parents);
const loose = USERS.filter(u=>["teacher","admin","pupil"].includes(u.role) && u.schoolId==null);
if(loose.length) group("gnoschool", T("amNoSchoolGroup"), loose);
}else{
/* één school gekozen: groepeer op rol, leerlingen per klas */
[["admin", T("roleAdmin")], ["teacher", T("roleTeacher")]].forEach(([role, label])=>{
const us = USERS.filter(u=>u.role===role);
if(us.length) group("role:"+role, label, us, true);
});
const pupils = USERS.filter(u=>u.role==="pupil");
if(currentUser.role==="teacher"){
if(pupils.length) group("pupils", T("amPupils"), pupils, true);
}else{
CLASSES.forEach(c=>{
const us = pupils.filter(u=>u.classId===c.id);
if(us.length) group("class:"+c.id, c.name, us, true);
});
const noClass = pupils.filter(u=>!u.classId);
if(noClass.length) group("class:none", T("amNoClass"), noClass, true);
}
const parents = USERS.filter(u=>u.role==="parent");
if(parents.length) group("parents", T("amParents"), parents);
}
const parents = USERS.filter(u=>u.role==="parent");
if(parents.length) pupilGroup("parents", T("amParents"), parents);
const loose = USERS.filter(isLoose);
if(loose.length) pupilGroup("noschool", T("amNoSchoolGroup"), loose);
master.appendChild(list);
split.appendChild(master);
split.appendChild(detail);

View file

@ -2,7 +2,7 @@
"use strict";
/* 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. */
const VERSION = "0.3.93-beta";
const VERSION = "0.3.94-beta";
(function(){
const tag = document.getElementById("verTag");
tag.textContent = "v"+VERSION;