Voeg 28 herkenbare kleurplaten en creatieve niveaus toe (v0.4.66-beta) #4
4 changed files with 46 additions and 10 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
0.3.14-beta
|
0.3.15-beta
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,16 @@
|
||||||
position:static; max-width:100%; box-shadow:0 6px 20px rgba(30,50,90,.12);
|
position:static; max-width:100%; box-shadow:0 6px 20px rgba(30,50,90,.12);
|
||||||
}
|
}
|
||||||
.pupil-card .widget-body{width:100%; height:100%;}
|
.pupil-card .widget-body{width:100%; height:100%;}
|
||||||
|
/* kijken-modus: alle interactie geblokkeerd (generiek, werkt voor elk
|
||||||
|
widgettype zonder eigen readonly-ondersteuning) + zichtbaar meekijk-label */
|
||||||
|
.pupil-card.watch{position:relative;}
|
||||||
|
.pupil-card.watch .widget-body{pointer-events:none; user-select:none;}
|
||||||
|
.pupil-watch-badge{
|
||||||
|
position:absolute; top:8px; right:10px; z-index:2; pointer-events:none;
|
||||||
|
font-size:12.5px; font-weight:700; color:var(--muted);
|
||||||
|
background:var(--panel, rgba(255,255,255,.85)); border-radius:999px; padding:3px 10px;
|
||||||
|
box-shadow:0 2px 8px rgba(30,50,90,.15);
|
||||||
|
}
|
||||||
.pupil-empty{margin:auto; color:var(--muted); font-size:16px; font-weight:600;}
|
.pupil-empty{margin:auto; color:var(--muted); font-size:16px; font-weight:600;}
|
||||||
/* floating add-button (FAB) */
|
/* floating add-button (FAB) */
|
||||||
#fab{
|
#fab{
|
||||||
|
|
|
||||||
|
|
@ -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.14-beta";
|
const VERSION = "0.3.15-beta";
|
||||||
(function(){
|
(function(){
|
||||||
const tag = document.getElementById("verTag");
|
const tag = document.getElementById("verTag");
|
||||||
tag.textContent = "v"+VERSION;
|
tag.textContent = "v"+VERSION;
|
||||||
|
|
@ -158,6 +158,7 @@ const I18N = {
|
||||||
roleSuper:"Overkoepelend beheerder", roleAdmin:"Schoolbeheerder",
|
roleSuper:"Overkoepelend beheerder", roleAdmin:"Schoolbeheerder",
|
||||||
roleTeacher:"Groepsleiding", rolePupil:"Leerling",
|
roleTeacher:"Groepsleiding", rolePupil:"Leerling",
|
||||||
pupilEmpty:"Je leerkracht heeft nog niets voor je klaargezet.",
|
pupilEmpty:"Je leerkracht heeft nog niets voor je klaargezet.",
|
||||||
|
pupilWatching:"meekijken",
|
||||||
amUsers:"Gebruikers", amClasses:"Klassen", amSchools:"Scholen", amOverarching:"Overkoepelend",
|
amUsers:"Gebruikers", amClasses:"Klassen", amSchools:"Scholen", amOverarching:"Overkoepelend",
|
||||||
amPickSchoolHint:"Kies eerst een school bij het tabblad “Overkoepelend”.",
|
amPickSchoolHint:"Kies eerst een school bij het tabblad “Overkoepelend”.",
|
||||||
amNewSchool:"+ School", amNewClass:"+ Klas", amNewTeacher:"+ Groepsleiding",
|
amNewSchool:"+ School", amNewClass:"+ Klas", amNewTeacher:"+ Groepsleiding",
|
||||||
|
|
@ -318,6 +319,7 @@ const I18N = {
|
||||||
roleSuper:"Overarching administrator", roleAdmin:"School administrator",
|
roleSuper:"Overarching administrator", roleAdmin:"School administrator",
|
||||||
roleTeacher:"Group leader", rolePupil:"Pupil",
|
roleTeacher:"Group leader", rolePupil:"Pupil",
|
||||||
pupilEmpty:"Your teacher hasn't set up anything for you yet.",
|
pupilEmpty:"Your teacher hasn't set up anything for you yet.",
|
||||||
|
pupilWatching:"watching",
|
||||||
amUsers:"Users", amClasses:"Classes", amSchools:"Schools", amOverarching:"Overarching",
|
amUsers:"Users", amClasses:"Classes", amSchools:"Schools", amOverarching:"Overarching",
|
||||||
amPickSchoolHint:"First pick a school in the “Overarching” tab.",
|
amPickSchoolHint:"First pick a school in the “Overarching” tab.",
|
||||||
amNewSchool:"+ School", amNewClass:"+ Class", amNewTeacher:"+ Group leader",
|
amNewSchool:"+ School", amNewClass:"+ Class", amNewTeacher:"+ Group leader",
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,26 @@
|
||||||
klaargezet (via een toewijzing aan de klas of de leerling zelf), in
|
klaargezet (via een toewijzing aan de klas of de leerling zelf), in
|
||||||
speelmodus (readonly) en zonder de sleep/vergroot/sluit-chrome van het bord.
|
speelmodus (readonly) en zonder de sleep/vergroot/sluit-chrome van het bord.
|
||||||
Geen momentopname: /my/assignment zoekt live in het bord van de leerkracht,
|
Geen momentopname: /my/assignment zoekt live in het bord van de leerkracht,
|
||||||
dus deze pagina pollt periodiek zodat nieuwe woorden vanzelf doorkomen. */
|
dus deze pagina pollt periodiek zodat nieuwe woorden vanzelf doorkomen.
|
||||||
|
Modus per toewijzing: "werken" (default, leerling werkt in de widget en
|
||||||
|
voortgang wordt gelogd) of "kijken" (alleen meekijken: alle interactie
|
||||||
|
geblokkeerd via een overlay, snellere poll zodat wijzigingen van de
|
||||||
|
leerkracht vlot doorkomen). */
|
||||||
const PUPIL_WIDGET_CATS = ["taal", "rekenen"];
|
const PUPIL_WIDGET_CATS = ["taal", "rekenen"];
|
||||||
|
const PUPIL_POLL_MS = { kijken: 5000, werken: 20000 };
|
||||||
const pupilView = document.getElementById("pupilView");
|
const pupilView = document.getElementById("pupilView");
|
||||||
let pupilPollTimer = null;
|
let pupilPollTimer = null;
|
||||||
let pupilLastSig = null;
|
let pupilLastSig = null;
|
||||||
|
let pupilMode = "werken";
|
||||||
|
|
||||||
function pupilAllowedDefs(){
|
function pupilAllowedDefs(){
|
||||||
return REGISTRY.filter(d => PUPIL_WIDGET_CATS.includes(d.cat));
|
return REGISTRY.filter(d => PUPIL_WIDGET_CATS.includes(d.cat));
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderPupilWidgets(widgets){
|
function renderPupilWidgets(widgets, mode){
|
||||||
pupilView.innerHTML = "";
|
pupilView.innerHTML = "";
|
||||||
const defs = pupilAllowedDefs();
|
const defs = pupilAllowedDefs();
|
||||||
|
const watch = mode === "kijken";
|
||||||
const usable = widgets
|
const usable = widgets
|
||||||
.map(w => ({ w, def: defs.find(d => d.id === w.id) }))
|
.map(w => ({ w, def: defs.find(d => d.id === w.id) }))
|
||||||
.filter(x => x.def);
|
.filter(x => x.def);
|
||||||
|
|
@ -27,30 +34,46 @@ function renderPupilWidgets(widgets){
|
||||||
}
|
}
|
||||||
usable.forEach(({ w, def }, idx)=>{
|
usable.forEach(({ w, def }, idx)=>{
|
||||||
const card = document.createElement("div");
|
const card = document.createElement("div");
|
||||||
card.className = "widget pupil-card";
|
card.className = "widget pupil-card" + (watch ? " watch" : "");
|
||||||
card.style.width = def.w + "px";
|
card.style.width = def.w + "px";
|
||||||
card.style.minHeight = def.h + "px";
|
card.style.minHeight = def.h + "px";
|
||||||
const body = document.createElement("div");
|
const body = document.createElement("div");
|
||||||
body.className = "widget-body";
|
body.className = "widget-body";
|
||||||
card.appendChild(body);
|
card.appendChild(body);
|
||||||
|
if(watch){
|
||||||
|
const badge = document.createElement("div");
|
||||||
|
badge.className = "pupil-watch-badge";
|
||||||
|
badge.textContent = "👁 " + T("pupilWatching");
|
||||||
|
card.appendChild(badge);
|
||||||
|
}
|
||||||
pupilView.appendChild(card);
|
pupilView.appendChild(card);
|
||||||
/* borden die vóór de invoering van stabiele widget-ids zijn opgeslagen
|
/* borden die vóór de invoering van stabiele widget-ids zijn opgeslagen
|
||||||
hebben nog geen wid - dan is positie in de lijst de terugval-identiteit,
|
hebben nog geen wid - dan is positie in de lijst de terugval-identiteit,
|
||||||
stabiel zolang de leerkracht de widgets op het bord niet herschikt */
|
stabiel zolang de leerkracht de widgets op het bord niet herschikt */
|
||||||
const widgetId = w.wid || (def.id + ":" + idx);
|
const widgetId = w.wid || (def.id + ":" + idx);
|
||||||
def.mount(body, w.state || null, { readonly:true, onProgress: (p)=>{
|
/* in kijken-modus geen voortgang: de leerling doet zelf niets */
|
||||||
|
const opts = watch ? { readonly:true } : { readonly:true, onProgress: (p)=>{
|
||||||
api("/my/progress", { method:"POST", body: { widgetId, widgetType: def.id, ...p } }).catch(()=>{});
|
api("/my/progress", { method:"POST", body: { widgetId, widgetType: def.id, ...p } }).catch(()=>{});
|
||||||
}});
|
}};
|
||||||
|
def.mount(body, w.state || null, opts);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pupilPoll(){
|
async function pupilPoll(){
|
||||||
try{
|
try{
|
||||||
const res = await api("/my/assignment");
|
const res = await api("/my/assignment");
|
||||||
const sig = JSON.stringify(res.widgets || []);
|
const mode = res.mode === "kijken" ? "kijken" : "werken";
|
||||||
|
/* modus in de signature zodat een moduswissel ook zonder widget-wijziging
|
||||||
|
een her-render (en dus de juiste overlay) oplevert */
|
||||||
|
const sig = mode + "|" + JSON.stringify(res.widgets || []);
|
||||||
if(sig !== pupilLastSig){
|
if(sig !== pupilLastSig){
|
||||||
pupilLastSig = sig;
|
pupilLastSig = sig;
|
||||||
renderPupilWidgets(res.widgets || []);
|
renderPupilWidgets(res.widgets || [], mode);
|
||||||
|
}
|
||||||
|
if(mode !== pupilMode){
|
||||||
|
pupilMode = mode;
|
||||||
|
clearInterval(pupilPollTimer);
|
||||||
|
pupilPollTimer = setInterval(pupilPoll, PUPIL_POLL_MS[mode]);
|
||||||
}
|
}
|
||||||
}catch(e){ /* stille mislukking - volgende poll probeert opnieuw */ }
|
}catch(e){ /* stille mislukking - volgende poll probeert opnieuw */ }
|
||||||
}
|
}
|
||||||
|
|
@ -58,9 +81,10 @@ async function pupilPoll(){
|
||||||
function startPupilView(){
|
function startPupilView(){
|
||||||
document.body.classList.add("pupil-mode");
|
document.body.classList.add("pupil-mode");
|
||||||
pupilLastSig = null;
|
pupilLastSig = null;
|
||||||
|
pupilMode = "werken";
|
||||||
pupilPoll();
|
pupilPoll();
|
||||||
clearInterval(pupilPollTimer);
|
clearInterval(pupilPollTimer);
|
||||||
pupilPollTimer = setInterval(pupilPoll, 20000);
|
pupilPollTimer = setInterval(pupilPoll, PUPIL_POLL_MS[pupilMode]);
|
||||||
}
|
}
|
||||||
function stopPupilView(){
|
function stopPupilView(){
|
||||||
document.body.classList.remove("pupil-mode");
|
document.body.classList.remove("pupil-mode");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue