Verbeter anatomie en plaatsing van avataraccessoires (v0.4.46-beta) #1
3 changed files with 66 additions and 19 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
0.3.10-beta
|
0.3.11-beta
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue