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 66 additions and 19 deletions
Showing only changes of commit aac7fd1c68 - Show all commits

View file

@ -1 +1 @@
0.3.10-beta 0.3.11-beta

View file

@ -448,6 +448,27 @@
return row; return row;
} }
/* vult een <select> met leerlingen gegroepeerd per klas (optgroup), gedeeld
tussen de Toewijzingen- en Voortgang-tab die beide één leerling kiezen */
function fillPupilSelect(sel, pupils){
sel.appendChild(new Option(T("amPickPupil"), ""));
const byClass = new Map();
pupils.forEach(u=>{
const key = u.classId || "none";
if(!byClass.has(key)) byClass.set(key, []);
byClass.get(key).push(u);
});
const addGroup = (label, us)=>{
if(!us || !us.length) return;
const og = document.createElement("optgroup");
og.label = label;
us.forEach(u=>og.appendChild(new Option(u.displayName, u.id)));
sel.appendChild(og);
};
CLASSES.forEach(c=>addGroup(c.name, byClass.get(c.id)));
addGroup(T("amNoClass"), byClass.get("none"));
}
/* leerling-omgeving: welk eigen bord ziet een klas (standaard), of een individuele /* leerling-omgeving: welk eigen bord ziet een klas (standaard), of een individuele
leerling (uitzondering voor wie op een ander niveau werkt) - zie roadmap-memo. */ leerling (uitzondering voor wie op een ander niveau werkt) - zie roadmap-memo. */
function renderToewijzingenPanel(panel){ function renderToewijzingenPanel(panel){
@ -468,22 +489,7 @@
panel.appendChild(h("div","am-group", T("amAssignPupils"))); panel.appendChild(h("div","am-group", T("amAssignPupils")));
const pupils = USERS.filter(u=>u.role==="pupil"); const pupils = USERS.filter(u=>u.role==="pupil");
const pupilSel = h("select","am-sel"); const pupilSel = h("select","am-sel");
pupilSel.appendChild(new Option(T("amPickPupil"), "")); fillPupilSelect(pupilSel, pupils);
const byClass = new Map();
pupils.forEach(u=>{
const key = u.classId || "none";
if(!byClass.has(key)) byClass.set(key, []);
byClass.get(key).push(u);
});
const addGroup = (label, us)=>{
if(!us || !us.length) return;
const og = document.createElement("optgroup");
og.label = label;
us.forEach(u=>og.appendChild(new Option(u.displayName, u.id)));
pupilSel.appendChild(og);
};
CLASSES.forEach(c=>addGroup(c.name, byClass.get(c.id)));
addGroup(T("amNoClass"), byClass.get("none"));
panel.appendChild(pupilSel); panel.appendChild(pupilSel);
const pupilRowHolder = h("div"); const pupilRowHolder = h("div");
panel.appendChild(pupilRowHolder); panel.appendChild(pupilRowHolder);
@ -497,6 +503,44 @@
}); });
} }
/* één regel in de voortgangstijdlijn van een leerling: widgettype, score en tijdstip */
function progressRow(ev){
const row = h("div","am-row");
row.appendChild(h("span","am-name", T("wg_"+ev.widgetType) || ev.widgetType));
const scoreParts = [];
if(ev.attempts) scoreParts.push(`${ev.correct}/${ev.attempts} ${T("mGoed")}`);
if(ev.stars) scoreParts.push("★".repeat(ev.stars));
row.appendChild(h("span","am-code", scoreParts.join(" · ")));
row.appendChild(h("span","am-code", new Date(ev.createdAt).toLocaleString(LANG==="nl" ? "nl-NL" : "en-GB")));
return row;
}
/* voortgang: leerkracht kiest een leerling (zelfde groepering per klas als
Toewijzingen) en ziet de volledige tijdlijn van diens afgeronde
widget-momenten (ronde sommen, voltooid woord, geknapte ballon). */
function renderVoortgangPanel(panel){
const schoolChosen = currentUser.role!=="super" || !!selSchool;
if(!schoolChosen){
panel.appendChild(h("div","guestnote", T("amPickSchoolHint")));
return;
}
const pupils = USERS.filter(u=>u.role==="pupil");
const pupilSel = h("select","am-sel");
fillPupilSelect(pupilSel, pupils);
panel.appendChild(pupilSel);
const eventsHolder = h("div","am-list");
panel.appendChild(eventsHolder);
pupilSel.addEventListener("change", async ()=>{
eventsHolder.innerHTML = "";
if(!pupilSel.value) return;
let events = [];
try{ events = (await api("/progress/pupil/"+pupilSel.value)).events || []; }
catch(e){ msg(e.message); return; }
if(!events.length){ eventsHolder.appendChild(h("div","guestnote", T("amProgressEmpty"))); return; }
events.forEach(ev=>eventsHolder.appendChild(progressRow(ev)));
});
}
/* zoekfilter voor de gebruikerslijst: verbergt niet-matchende rijen en lege groepen /* zoekfilter voor de gebruikerslijst: verbergt niet-matchende rijen en lege groepen
via style.display i.p.v. een her-render, zodat het zoekveld focus houdt tijdens via style.display i.p.v. een her-render, zodat het zoekveld focus houdt tijdens
het typen (een volledige render() zou het veld elke toets opnieuw aanmaken) */ het typen (een volledige render() zou het veld elke toets opnieuw aanmaken) */
@ -602,6 +646,7 @@
tabDefs.push(["klassen", T("amClasses")]); tabDefs.push(["klassen", T("amClasses")]);
tabDefs.push(["gebruikers", T("amUsers")]); tabDefs.push(["gebruikers", T("amUsers")]);
tabDefs.push(["toewijzingen", T("amAssignments")]); tabDefs.push(["toewijzingen", T("amAssignments")]);
tabDefs.push(["voortgang", T("amProgress")]);
if(!tabDefs.some(([t])=>t===adminTab)) adminTab = tabDefs[0][0]; if(!tabDefs.some(([t])=>t===adminTab)) adminTab = tabDefs[0][0];
const tabsBar = h("div","ed-tabs"); const tabsBar = h("div","ed-tabs");
@ -614,7 +659,7 @@
}); });
modal.appendChild(tabsBar); modal.appendChild(tabsBar);
const panels = { scholen: renderScholenPanel, klassen: renderKlassenPanel, gebruikers: renderGebruikersPanel, toewijzingen: renderToewijzingenPanel }; const panels = { scholen: renderScholenPanel, klassen: renderKlassenPanel, gebruikers: renderGebruikersPanel, toewijzingen: renderToewijzingenPanel, voortgang: renderVoortgangPanel };
tabDefs.forEach(([t])=>{ tabDefs.forEach(([t])=>{
const panel = h("div","am-tabpanel"); const panel = h("div","am-tabpanel");
panel.dataset.panel = t; panel.dataset.panel = t;

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.10-beta"; const VERSION = "0.3.11-beta";
(function(){ (function(){
const tag = document.getElementById("verTag"); const tag = document.getElementById("verTag");
tag.textContent = "v"+VERSION; tag.textContent = "v"+VERSION;
@ -175,6 +175,7 @@ const I18N = {
amAssignments:"Toewijzingen", amAssignClasses:"Per klas (standaard)", amAssignPupils:"Per leerling (uitzondering)", amAssignments:"Toewijzingen", amAssignClasses:"Per klas (standaard)", amAssignPupils:"Per leerling (uitzondering)",
amPickPupil:"— kies een leerling —", amNoAssignment:"— geen toewijzing —", amPickPupil:"— kies een leerling —", amNoAssignment:"— geen toewijzing —",
amAssignedAs:"Toegewezen:", amAssign:"Toewijzen", amAssignSaved:"Toewijzing opgeslagen.", amAssignedAs:"Toegewezen:", amAssign:"Toewijzen", amAssignSaved:"Toewijzing opgeslagen.",
amProgress:"Voortgang", amProgressEmpty:"Nog geen voortgang voor deze leerling.",
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",
amResetClass:"reset wachtwoorden klas", amResetSchool:"reset alle leerlingwachtwoorden", amResetClass:"reset wachtwoorden klas", amResetSchool:"reset alle leerlingwachtwoorden",
@ -334,6 +335,7 @@ const I18N = {
amAssignments:"Assignments", amAssignClasses:"Per class (default)", amAssignPupils:"Per pupil (override)", amAssignments:"Assignments", amAssignClasses:"Per class (default)", amAssignPupils:"Per pupil (override)",
amPickPupil:"— pick a pupil —", amNoAssignment:"— no assignment —", amPickPupil:"— pick a pupil —", amNoAssignment:"— no assignment —",
amAssignedAs:"Assigned:", amAssign:"Assign", amAssignSaved:"Assignment saved.", amAssignedAs:"Assigned:", amAssign:"Assign", amAssignSaved:"Assignment saved.",
amProgress:"Progress", amProgressEmpty:"No progress for this pupil yet.",
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",
amResetClass:"reset class passwords", amResetSchool:"reset all pupil passwords", amResetClass:"reset class passwords", amResetSchool:"reset all pupil passwords",