All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 9s
- Nieuwe tabel `assignments`: een leerkracht koppelt één van haar eigen borden aan een klas (standaard) of een individuele leerling (uitzondering, voor wie op een ander niveau werkt). - Geen momentopname: /my/assignment zoekt het bord live op bij de leerkracht, dus nieuwe woorden die zij toevoegt komen vanzelf door zodra de leerling-pagina opnieuw pollt (elke 20s). - Leerlingen loggen in op een vereenvoudigde pagina zonder whiteboard/ tekengereedschap: enkel de toegewezen taal-/rekenwidgets, als vaste (niet-sleepbare) kaarten in speelmodus. - Speelmodus verbergt bewerkfuncties in Ankerwoorden (plaatje kiezen, woord typen, kleur wijzigen) en Letterblokken (thema/woordbeheer) - overige widgets waren al zuiver speelgericht. - Elk bord krijgt een stabiel id (board.js) zodat een toewijzing een bord blijft vinden ook na hernoemen of herordenen. - Nieuw tabblad "Toewijzingen" in het beheerpaneel: per klas of leerling een eigen bord kiezen, met een expliciete toewijs-stap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DuxHJtk5aHe2pA3xwCLEAk
64 lines
2.1 KiB
JavaScript
64 lines
2.1 KiB
JavaScript
/* teach - leerling-omgeving: toont enkel de widgets die de leerkracht heeft
|
|
klaargezet (via een toewijzing aan de klas of de leerling zelf), in
|
|
speelmodus (readonly) en zonder de sleep/vergroot/sluit-chrome van het bord.
|
|
Geen momentopname: /my/assignment zoekt live in het bord van de leerkracht,
|
|
dus deze pagina pollt periodiek zodat nieuwe woorden vanzelf doorkomen. */
|
|
const PUPIL_WIDGET_CATS = ["taal", "rekenen"];
|
|
const pupilView = document.getElementById("pupilView");
|
|
let pupilPollTimer = null;
|
|
let pupilLastSig = null;
|
|
|
|
function pupilAllowedDefs(){
|
|
return REGISTRY.filter(d => PUPIL_WIDGET_CATS.includes(d.cat));
|
|
}
|
|
|
|
function renderPupilWidgets(widgets){
|
|
pupilView.innerHTML = "";
|
|
const defs = pupilAllowedDefs();
|
|
const usable = widgets
|
|
.map(w => ({ w, def: defs.find(d => d.id === w.id) }))
|
|
.filter(x => x.def);
|
|
if(!usable.length){
|
|
const hint = document.createElement("div");
|
|
hint.className = "pupil-empty";
|
|
hint.textContent = T("pupilEmpty");
|
|
pupilView.appendChild(hint);
|
|
return;
|
|
}
|
|
usable.forEach(({ w, def })=>{
|
|
const card = document.createElement("div");
|
|
card.className = "widget pupil-card";
|
|
card.style.width = def.w + "px";
|
|
card.style.minHeight = def.h + "px";
|
|
const body = document.createElement("div");
|
|
body.className = "widget-body";
|
|
card.appendChild(body);
|
|
pupilView.appendChild(card);
|
|
def.mount(body, w.state || null, { readonly:true });
|
|
});
|
|
}
|
|
|
|
async function pupilPoll(){
|
|
try{
|
|
const res = await api("/my/assignment");
|
|
const sig = JSON.stringify(res.widgets || []);
|
|
if(sig !== pupilLastSig){
|
|
pupilLastSig = sig;
|
|
renderPupilWidgets(res.widgets || []);
|
|
}
|
|
}catch(e){ /* stille mislukking - volgende poll probeert opnieuw */ }
|
|
}
|
|
|
|
function startPupilView(){
|
|
document.body.classList.add("pupil-mode");
|
|
pupilLastSig = null;
|
|
pupilPoll();
|
|
clearInterval(pupilPollTimer);
|
|
pupilPollTimer = setInterval(pupilPoll, 20000);
|
|
}
|
|
function stopPupilView(){
|
|
document.body.classList.remove("pupil-mode");
|
|
clearInterval(pupilPollTimer);
|
|
pupilPollTimer = null;
|
|
pupilView.innerHTML = "";
|
|
}
|