Bij veel widgets nam de instellingenstrook te veel hoogte in, vooral bij een
smal widgetvenster waar de rij naar meerdere regels uitwaaierde. Nieuw
gedeeld patroon: besturing die voortdurend nodig is (kleur, niveau,
woordbron) blijft in één compacte rij zichtbaar; besturing die maar zelden
wordt aangepast (thema, geluid aan/uit, invoerwijze, bereik) gaat achter een
inklapbaar ⚙-paneel. Dit patroon bestond al voor klok/geld/rekengetallen/
wereld (learningShell() in learning.js) - nu als widgetGear()/gearField() in
core.js beschikbaar voor de rest van de app, met dezelfde .edu-settings-
opmaak zodat het overal hetzelfde oogt en werkt.
- kleurplaten: twee volle rijen (thema/plaat + kwast/emmer/gum/kleur/dikte/
hulp/reset/klaar) teruggebracht naar één vaste rij (gereedschap, kleur,
dikte, klaar) plus het ingeklapte paneel (thema, plaat, kleurhulp, reset).
Losstaand: coloring.css gebruikte @media(max-width:620px) in plaats van de
@container widget-conventie die de rest van de app gebruikt, waardoor die
regels nooit afgingen bij het verkleinen van het widgetvenster zelf - nu
gecorrigeerd.
- letterblokken: geluid, invoerwijze en aantal kaarten in het paneel; niveau
en woordbron blijven vast.
- rekenwidgets (optellen/aftrekken/keer/delen/procenten): geluid en
invoerwijze in het paneel; niveau blijft vast.
- ballonnenwoord: geluid in het paneel.
- flitswoorden: flitstijd in het paneel.
- getallenlijn: het hele bereik-instelblok (van/tot/stap/nieuw) in het
paneel - dat stond toch al uit voor leerlingen met een beheerd niveau.
- zinsbouwer: het rijtje voor eigen woorden toevoegen in het paneel; de
speelknoppen (verrassing/ongedaan/wissen/voorlezen) blijven vast.
- timer: geluid en weergavevorm in het paneel; starttijden en start/reset
blijven vast.
- geluidsmeter: de twee drempelschuifjes plus de privacynotitie in het
paneel.
Widgets die dit patroon al hadden (klok, geld, breuken, plaatswaarde,
woordsoorten, bomen/vogels/planten, topografie, stemming, stemming-poll,
dagplanning) of waar de rij al compact genoeg was (schrijfblad, hakken en
plakken, dobbelstenen, notities, naamtrekker) zijn ongewijzigd gelaten.
Geverifieerd door elke aangepaste widget live via de echte makeWidget()/
REGISTRY in een headless browser te openen, het paneel open en dicht te
klappen en te controleren op consolefouten - ook op de minimale
widgetbreedte (coloring, minW 390). 202 tests groen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011YErxhic5w9K57zmt8Q1uS
Kwast en verfemmer werkten al, maar het resultaat was onzichtbaar: de
contourlaag zette fill="#fff" op elk vak en vertrouwde op
mix-blend-mode:multiply om dat onschadelijk te maken. Doordat .coloring-ink
zelf een stacking context is (position+z-index), vormt die een geisoleerde
blendgroep zonder achtergrond, en werd het wit gewoon dekkend over de hele
tekening gelegd. Live nagemeten met headless Chromium.
- Tekenmodel omgezet naar een echte schildersvolgorde in een enkele SVG: elk
vak wordt uitgeklapt naar vak -> verflaag -> contour, zodat verf zichtbaar
blijft en latere vakken de verf en contour van eerdere vakken afdekken.
Daarmee kijk je ook niet meer door figuren heen.
- Canvas vervangen door SVG-streken: geen opschalingsonscherpte meer en geen
donkere naden (dekking staat per streek op de groep, niet per segment).
- Kwast blijft binnen de lijnen als hulp, gestuurd door niveau: groep 1-4 op
niveau 1 en 2, groep 5-8 op niveau 1, daarboven vrij schilderen.
- Verfemmer dekt een vak volledig; de gum pelt de bovenste laag af (eerst de
vulling, daarna de streken eronder).
- Kleurwijzer toegevoegd: op niveau 1 laat een stip per vak de voorgestelde
kleur zien, op niveau 2 op te vragen met een knop, op niveau 3 uit.
- Niveau sloopt de tekening niet meer: data-tier staat alleen op groepen en
detaillijnen, dus een rekwisiet verdwijnt als geheel en de plaat is op elk
niveau een complete tekening. Niveau 3 voegt alleen fijn lijnwerk toe.
- Atlas hertekend naar 20 platen, 5 per groepenband en 1 per thema. Twee
lijndiktes, vakken op maat van de band, geen evenodd-gaten, en composities
met voor-, midden- en achtergrond.
- partBelow/elementFromPoint en het omzetten van pointer-events vervallen:
aanwijzen gebeurt meetkundig met isPointInFill/isPointInStroke.
- langchange-listener ruimt zichzelf op na demontage.
- Staat bewaart nu streken in plaats van een PNG; oud werk met een ink-PNG
blijft zichtbaar.
- Tests: asserties die de bug vastzetten verwijderd en vervangen door een
regressietest die verbiedt dat CSS een fill op een kleurvak zet, plus
controles op gesloten vakken, geen transform, tier-regels, vakaantallen per
niveau en de clip-matrix.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011YErxhic5w9K57zmt8Q1uS
- vervang alle 28 kleurplaten door samenhangende scènes met organische contouren en leeftijdsgerichte detaillering
- houd buiten- en binnenlijnen zichtbaar boven kwastwerk en sluit verfemmerkleuren zonder witte rand aan
- borg gesloten kleurvakken, anatomische laagvolgorde en scene-opbouw met uitgebreide regressietests
- laat de gum ook verfpotvullingen bij tikken en slepen verwijderen
- vervang dubbele filterlagen door één gemaskeerde contourlaag zonder witte halo
- verberg overlappende herkenningshulplijnen en dek achterliggende contouren correct af
- voeg regressietests toe voor gum, vulranden en lijnlagen
Gewijzigde functionaliteiten:
- Vervang losse geometrische dierdelen door vloeiende Bézier-silhouetten met geloofwaardiger anatomie.
- Schilder poten, staarten, vinnen, vleugels, wielen en andere appendages achter het hoofdsilhouet voor aansluitende contouren.
- Voeg een SVG-occlusiefilter toe dat alleen werkelijk zichtbare lijnen boven kwast en verfpot toont.
- Verfijn lijngewichten, witte contrastrand, wielkasten, manen en objectcontouren.
- Geef kwast, verfpot en gum zichtbare labels en verbeter ARIA-groepering van gereedschappen en palet.
- Voeg regressietests toe voor organische contouren, schildervolgorde, gesloten kleurvakken en UX-bediening.
Tests:
- npm test (201 geslaagd)
Gewijzigde functionaliteiten:
- Vervang foutgevoelige zwarte en witte SVG-vullingen door transparante contourlagen.
- Laat de verfpot rechtstreeks de aanklikbare kleurvakken bedienen.
- Vervang het kleurpotlood door een vloeiende, pendrukgevoelige kwast met eigen icoon en cursor.
- Migreer opgeslagen potloodstate automatisch naar het nieuwe kwastgereedschap.
- Voeg regressietests toe voor achtergrond, laagweergave en gereedschapsinvoer.
Tests:
- npm test (201 geslaagd)
Gewijzigde functionaliteiten:
- Splits kleurplaten in kleur-, potlood- en bovenste inktlaag zodat contouren zichtbaar blijven.
- Versterk lijnen met een lichte contrastrand en donkere inkt, met behoud van de juiste overlappingen.
- Vernieuw werkvlak, gereedschappen en kleurenpalet voor een krachtiger grafische uitstraling.
- Voeg regressietests toe voor laagvolgorde en inktweergave.
Tests:
- npm test (201 geslaagd)
Gewijzigde functionaliteiten:
- Brengt een rustige lijnhiërarchie aan met subtiele buitenkaders, stevige kleurvlakken en lichtere binnenlijnen.
- Voegt herkenbare textuurdetails toe aan onder meer vlinder, herfstboom, taart, zeedieren, molen, raket en kasteel.
- Verbetert het fietsframe in de duurzame-stadplaat en markeert kleurvlakken bij aanwijzen met de verfemmer.
- Borgt het consistente SVG-profiel voor alle 28 kleurplaten met aanvullende tests.
Tests: 201 geslaagd (npm test); 5 gerichte kleurplaattests geslaagd.
Gewijzigde functionaliteiten:
- De open stippen in de doelvakken stonden links-boven in hun rastercel in
plaats van gecentreerd, waardoor het patroon scheef oogde; ze staan nu op
dezelfde as als de gevulde stippen.
- De stippen van de geldblokken en van alle cijferblokken in een smalgemaakte
widget staken onder het blok uit. De stipmaat komt nu uit een variabele die
elk bloktype naast zijn eigen hoogte zet, in plaats van uit losse
hardgecodeerde regels per widget.
- De smalle-widget-weergave verkleint alleen nog de breedte; blokhoogtes
blijven gelijk, want juist het verkleinen van de hoogte duwde het raster naar
buiten. Letterblokken krijgen daar een passend kleiner cijfer/letterformaat.
- Nieuw vangnet: het raster houdt altijd zijn maat en het label geeft mee als
een blokformaat krap is, zodat een nieuw blokformaat dit niet opnieuw kan
veroorzaken.
Tests: 196 geslaagd (4 nieuw in test/dot-grid.test.js; die vier vallen ook
daadwerkelijk om op de oude CSS). Daarnaast in de browser opgemeten voor alle
zeven blokcontexten, bij normale en smalle widgetbreedte, plus screenshots en
een controle in de echte leerlingweergave.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126hjBPD2ggZ2LEoDYZSW7S
Gewijzigde functionaliteiten:
- Letterblokken logt per afgerond woord hoeveel pogingen het kostte en welke
letter op welke plek fout ging (beide invoerwijzen: blokken slepen en typen).
- Ballonnenwoord logt nu ook een verloren woord; dat leverde tot nu toe geen
enkele voortgang op. Een gewonnen woord telt de fout geraden letters mee.
- Flitswoorden stuurt de bestaande zelfcheck ("Gelukt" / "Nog oefenen") door
naar de voortgang; die uitkomst werd eerder weggegooid.
- Hakken & plakken krijgt dezelfde zelfcheck en daarmee als laatste taalwidget
een goed/fout-moment; de oefening zelf verandert niet.
- Voortgang-tab toont de fouten van taal: naast fout afgesloten opdrachten ook
"na N pogingen goed" (letterblokken kent geen faalmoment) en zelfchecks.
- Reeksstappen met flitswoorden of hakken & plakken wachten nu op een echt
afgerond moment in plaats van meteen te completeren.
Tests: 192 geslaagd (7 nieuw), plus live nagelopen in de leerlingweergave met
echte interactie per widget en een screenshot van de Voortgang-tab.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126hjBPD2ggZ2LEoDYZSW7S
Gewijzigde functionaliteiten:
- Centreert doelvakken in letter-, reken-, klok-, geld-, plaatswaarde- en wereldwidgets.
- Houdt lange woordrijen scrollbaar zonder de eerste vakken af te snijden.
- Centreert kleinere geplaatste cijferblokken binnen hun doelvak.
- Verwijdert de links uitgelijnde compacte woordrij.
Tests: 160 geslaagd.
Gewijzigde functionaliteiten:
- Voegt vijf afwisselende avatardansen toe.
- Houdt lichaam, haar en accessoires als een verbonden SVG-figuur.
- Danst na afgeronde woordgroepen, flitsrondes, galgjerondes en rekenrondes.
- Respecteert verminderde beweging met een stil feestbeeld.
Tests: 159 geslaagd; npm audit: 0 kwetsbaarheden.
- Bug gevonden en bevestigd (niet blind aangenomen): math.js riep
onProgress maar op ÉÉN plek aan, in endRound(), NA een heel blok van
10 sommen, met alleen het geaggregeerde totaal. Eén sessie van 10
sommen - "een groep opdrachten" - leverde dus precies 1 rij op in
progress_events, niet 10, en maakte "welke som ging fout" onmogelijk
te zien (alleen een totaaltelling per blok).
- Fix: onProgress verplaatst naar check(), bij elke afgeronde som (goed
op de eerste keer, of opgeven na 3 pogingen) - een sessie van 10
sommen levert nu 10 progress_events-rijen op, elk met een nieuw
optioneel detail-veld (welke som, gegeven antwoord, juist antwoord).
letters.js/ball.js blijven deze ronde ongemoeid (hun granulariteit
veroorzaakte niet deze bug).
- Nieuwe kolom progress_events.detail (JSONB, nullable, puur additief -
db/020_progress_detail.sql). POST /my/progress accepteert het
optioneel; te groot/geen plain object wordt stilzwijgend genegeerd
zonder de rest van de log-poging te laten falen (detail is decoratief,
geen kernfunctionaliteit).
- Voortgang-tab (admin.js) herontworpen, zelfde ontwerptaal als de
eerdere School-navigator-herbouw: vakgebied-tabs, een
klassenmanagement-infobadge (Groep {n} · Niveau {n}, opgehaald via de
bestaande /levels/pupil/:id-route) zodat resultaten meteen tegen het
toegewezen niveau afgezet kunnen worden, een met de hand getekende
SVG-nauwkeurigheidsring + staafdiagram (goed/fout per dag, laatste 14
dagen - geen library, zelfde aanpak als avatar.js) en een "recente
fouten"-lijst die precies toont welke som fout ging. De bestaande
ruwe tijdlijn blijft eronder staan, niets is verwijderd.
- Terzijde gevonden en gefixt: .am-btn.active bestond nergens in de
CSS, waardoor de vakgebied-tabs (hier én in Klassenmanagement,
v0.4.34-beta) geen enkele visuele aanduiding hadden welke actief was.
- Tests: test/progress-logging.test.js uitgebreid met 4 tests voor het
detail-veld (opgeslagen, te groot genegeerd, geen plain object
genegeerd, afwezig blijft null). Volledige testsuite: 132/132.
- Live geverifieerd: een math.js-sessie met een mix van goede/foute
sommen doorlopen en bevestigd dat er 3 aparte POST /my/progress-
aanroepen gebeuren voor 3 sommen (niet 1 aggregaat), elk met het
juiste detail; de herbouwde Voortgang-tab geopend met gemockte data
en met screenshots bevestigd dat de nauwkeurigheidsring (38% = 3/8,
rekenkundig geverifieerd), het klassenmanagement-infobadge, de
staafdiagram en de "recente fouten"-lijst (met de daadwerkelijke som)
correct tonen, én dat de active-tab-fix ook op de Klassenmanagement-
tab zichtbaar is.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EPxzBVRXZZnBPvSAaPAbJ
- Kernprobleem: de CSS-laagjesversie (losse divs met percentage-posities
en z-index) had onderdelen die los van het lichaam hingen en een
tekenvolgorde die niet klopte (soort-specifieke delen soms achter
hoofd/lijf verstopt, soms er los voor zwevend). SVG lost dit
structureel op: tekenvolgorde = laagvolgorde, geen z-index nodig, en
elk onderdeel is een gebogen path/ellips die het silhouet van het
vorige onderdeel ruim overlapt in plaats van ernaast te zweven.
- Onderzocht hoe gangbare avatar-generators (DiceBear, Avataaars) dit
aanpakken: vaste 100x100 viewBox, onderdelen als SVG-groepen in de
juiste volgorde, kleur via directe fill-waarden i.p.v. CSS-variabelen
in SVG. Dat patroon hier toegepast, geen code overgenomen.
- Elke soort (dino/monster/dier) is nu een samenhangend lichaam: poten,
armen, staart/oren, buikvlek en gezicht overlappen allemaal duidelijk
met het hoofd/lijf. Dino: rugstekels, snuit met neusgaten, glimlach.
Monster: hoorntjes, brede mond met slagtandjes, asymmetrische ogen.
Dier: ronde oren, beer-snuit, kleine staart.
- Haar (spits/krullen/paardenstaart/mohawk) en accessoires (pet/kroon/
bril/strik/sjaal/cape/badge) opnieuw getekend zodat ze ook echt op
hun naam lijken, i.p.v. simpele gekleurde blokjes.
- Regel toegevoegd: een pet of kroon dekt het hele bovenhoofd af, dus
onderliggend haar wordt dan niet getekend (gaf anders rommelige,
half verstopte plukjes rond de rand) - een paardenstaart blijft wel
zichtbaar, want die hangt naar opzij.
- Kleuren (lichter voor buik/snuit, donkerder voor poten/staart/
rugstekels) worden nu berekend uit de gekozen lichaamskleur zelf
(avatarShade-helper), i.p.v. via CSS filter:brightness().
- CSS: alle oude .av-* laag-regels (~65 regels) verwijderd; alleen
afmetingen (sm/md/lg) en de bestaande instellingen/widget/
aanmoedigings-CSS blijven staan.
- Geverifieerd: alle vijf bestaande scenario's (opslaan, widget,
School-navigator-badge met een echte klas vol verschillende
personages, math.js-aanmoediging, ongeldige input), plus uitgebreide
screenshot-rondes van losse onderdelen, alle soort/haar/accessoire-
combinaties en alle drie weergavegroottes (24/44/180px) vóór het
committen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EPxzBVRXZZnBPvSAaPAbJ
- Buikvlek (lichter gekleurde ovaal) op de romp - een klassiek dino-kenmerk
dat meteen de "kleurvlek zonder vorm"-indruk wegneemt.
- Twee kleine pootjes onderaan en twee stompe armpjes opzij (T-rex-stijl) -
het lichaam stond eerder als een rond blok zonder ledematen.
- Staart herzien naar een echte taps toelopende vorm (clip-path) i.p.v. de
ronde druppelvorm van hiervoor.
- Alleen voor soort "dino" - monster/dier ongewijzigd, geen regressie
(gecontroleerd via de screenshot-galerij van alle drie soorten samen).
- Geverifieerd op alle vijf bestaande scenario's (opslaan, widget,
School-navigator-badge, math.js-aanmoediging, ongeldige input) én
opnieuw op alle drie weergavegroottes (24/44/180px) vóór het committen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EPxzBVRXZZnBPvSAaPAbJ
- Elk personage kreeg ogen (was volledig gezichtsloos - de kernoorzaak van de
lage beeldkwaliteit: een gekleurde vlek zonder gezicht oogt nooit als een
figuur, ongeacht soort/haar/accessoires).
- Dino kreeg een snuitje met neusgaten, een duidelijk zichtbaar staartje en
een derde, groter/donkerder rugstekel-plaatje - hiervoor waren de
rugstekels aanwezig maar onzichtbaar (z-index onder het lijf/hoofd, zie
vorige commit), nu bewust vóór het silhouet getekend zodat ze altijd tonen.
- Snuitje stond eerst z-index-onder de rugstekels (dus zelf ook onzichtbaar,
identieke fout als hierboven) - z-index verhoogd zodat het snuitje altijd
vóór de rugstekels ligt, wat ook anatomisch klopt (snuit zit vooraan).
- Geverifieerd met alle vijf scenario's uit de vorige verificatie (opslaan,
widget, School-navigator-badge, math.js-aanmoediging) plus een losse
screenshot-galerij op alle drie weergavegroottes (24/44/180px).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EPxzBVRXZZnBPvSAaPAbJ
- Nieuwe migratie db/018_user_avatar.sql: kolom avatar_data (jsonb) op users.
- publicUser() geeft avatar overal automatisch mee (login, /auth/me,
/admin/users) - bestaande school/klas-rechten regelen vanzelf wie welke
personages ziet, geen nieuwe permissie-sleutel nodig.
- Nieuwe route PUT /me/avatar (open voor elke ingelogde rol, zelfde patroon
als /me/data): valideert soort/kleuren/haar/accessoires, slaat de eigen rij op.
- Nieuwe gedeelde module public/js/avatar.js: personage samenstellen uit
soort (dino/monster/dier - elk met een vast eigen lichaamsdeel, ook de
gevraagde dinostekels), lichaams- en haarkleur, haarstijl en hoofd-/
lichaamsaccessoires; gedeelde editor-UI voor zowel de instellingen-sectie
"Mijn personage" als de nieuwe widget.
- Instellingen-sectie "Mijn personage" (cms.js-patroon) - de leerling-toegang,
want widgets van categorie "class" zijn niet toewijsbaar in het
afgeschermde leerling-speelscherm.
- Widget 🦖 toegevoegd aan het bord (categorie "class") voor staf en
volledige-whiteboard-gebruikers.
- School-navigator (admin.js): leerkracht/beheerder ziet nu het personage
van elk klaslid in de personenlijst i.p.v. altijd de initialen-cirkel.
- Voorbereiding gerelateerd roadmappunt: math.js toont het eigen personage
kort naast "Goed!" als aanmoediging (pilot in één widget, geen nieuw
feedbacktype); zonder ingesteld personage blijft het gedrag ongewijzigd.
- Vertalingen (nl+en) voor de nieuwe widget, instellingen-sectie en editor.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EPxzBVRXZZnBPvSAaPAbJ
- Geluidsmeter: meet het klasgeluid live via de microfoon in een verticale
meter (rustig/pratend/te luid). Twee aanpasbare streefniveaus ("Rustig
tot" / "Te luid vanaf") laten de leerkracht de meter afstemmen op het
eigen lokaal en apparaat. Microfoon staat standaard uit en start alleen
na een expliciete klik; er wordt niets opgenomen of verstuurd, alles
blijft lokaal in de browser. Stopt de microfoonstream vanzelf zodra de
widget van het bord verdwijnt, ook als "Stop" niet eerst is ingedrukt.
- Gevoelszones: individuele check-in met vier zones (blauw/groen/geel/
rood, Zones of Regulation-stijl) - elke zone geeft een korte uitleg én
een concrete tip om jezelf te helpen. Anders dan de bestaande
Gevoelsmeter (mood.js), die een anonieme klaspoll is.
- Ademhalingsoefening: een groeiende/krimpende cirkel begeleidt rustig
ademhalen in drie instelbare tempo's (4-4, 4-7-8, box breathing),
met rondjesteller.
- Complimentenmachine: trekt een willekeurig compliment uit twintig
kindvriendelijke complimenten, met dezelfde spin-en-onthul-animatie als
de namenkiezer.
- Alle vier volledig tweetalig (nl/en), toegevoegd aan de mobiele-dekking-
test, en geverifieerd in de browser inclusief een echte (fake) micro-
foonstream voor de geluidsmeter.
- Bomen/vogels/planten/topografie verstopten "Niveau" als een los
keuzeveld onderin het inklapbare Instellingen-paneel; de oefenklok,
het geldwidget, plaatswaarde en rekenwidgets tonen niveau altijd als
een knoppenrij bovenaan, direct zichtbaar tijdens het spelen.
- Niveau is nu overal dezelfde knoppenrij (Niveau 1/2/3, met uitleg per
knop via title, net als bij de oefenklok) direct in de bovenbalk naast
de score - geen Instellingen meer nodig om niveau te wisselen.
- Niveau wisselen zet score en reeks terug naar 0, zoals bij de andere
oefenwidgets (voorheen bleef de score gewoon doorlopen).
- Topografie: de knoppenrij verdwijnt bij "Landsdelen", waar niveau toch
al niet van toepassing was - zelfde gedrag als voorheen, nu alleen
consistent met de rest.
- Bomen, vogels en wilde planten krijgen twee nieuwe werkvormen naast
Leren/Quiz: Flitskaarten (naam kort tonen, dan zelftoets - zelfde opzet
als het losse Flitswoorden-widget) en Letterblokken (de naam met
sleepblokken spellen, zelfde mechaniek als de letterblokken-widget,
inclusief puntenpatroon per letter).
- Topografie krijgt dezelfde twee werkvormen: flitskaarten tonen de kaart
met de plek pas gelabeld na onthullen, letterblokken laat de naam van de
gemarkeerde provincie/plaats/rivier/werelddeel spellen.
- Letterblokken werkt ook bij namen met spaties (bv. "Witte
paardenkastanje") - spaties worden een visuele tussenruimte, geen vak.
- Geverifieerd door alle vier widgets (bomen/vogels/planten/topografie)
volledig te spelen: flitskaart onthullen + zelftoets, en een woord
volledig spellen puur op basis van de getoonde puntenpatronen.
- De cijferblokken (oefenklok, geldwidget) hergebruikten de braille a-j-
patronen, die nooit de onderste rij (posities 3/6) gebruiken - daardoor
leken alle tien blokken op elkaar. Eigen DIGIT_DOTCODE-tabel die alle
zes stippen inzet, geeft elk cijfer nu een echt eigen vorm.
- Plaatswaardetabel-widget had geen enkele oefenvorm (alleen een vrij
invoerveld); nieuwe "Bouwen"-stand met drie niveaus (T/E, H/T/E, of
HD/TD/D/H/T/E) laat kinderen een getal opbouwen door cijferblokken in
de juiste kolom te slepen, met score/reeks en directe feedback - zelfde
bouwsteen als de oefenklok/het geldwidget. De vrije verkenstand blijft
ongewijzigd bestaan.
- Bijvangst: instellingenvelden met .hidden (bv. "24-uursklok" bij de
oefenklok) werden nooit echt verborgen door een CSS-specificiteitsbotsing
(.edu-controls label versloeg [hidden]); toegevoegde regel herstelt dit
voor alle leerwidgets.
- Nieuwe Cast-knop (📡) op de whiteboard-toolbar opent een sheet om het
geopende bord - of één widget erop met kijken/werken - direct naar een
klas of leerling uit te zenden, zonder om te weg via Instellingen.
- Hergebruikt de bestaande PUT/DELETE /assignments/class|pupil routes
ongewijzigd; geen serverwijziging nodig.
- Instellingen > Toewijzingen blijft bestaan maar toont nu alleen de
huidige toewijzing + een "Loskoppelen"-knop (aanmaken/wijzigen gebeurt
voortaan via Cast).
Volledige herbouw van het "School"-tabblad naar het goedgekeurde concept
(tegel-overzicht -> gefocust detailscherm), i.p.v. drie secties op één lange
pagina. Zelfde patroon op elk niveau:
- "alle scholen" (systeemmanager): tegel per school + Systeemmanagers/Ouders/
Zonder school + "+ School"
- een school: tegel per klas + Schoolbeheerder/Niet ingedeeld/Ouders/
Aanmeldingen + "+ Klas"; "⋯" toont schoolbeheer (naam/verwijderen, alleen
systeemmanager)
- een klas: Groepsleiding en Leerlingen als twee eigen sublijstjes, elk met
een eigen "+"; "⋯" toont klasbeheer (verplaatsen/resetten/verwijderen)
- een platte groep: één lijst, evt. met "+"
Personen en aanmeldingen openen nu in een sheet (bestaande userTools()/
requestTools() vrijwel ongewijzigd hergebruikt) i.p.v. een los detailpaneel.
Zoeken vult, op tegel-niveau, het scherm met een systeembrede resultatenlijst.
Een leerkracht (groepsleiding) blijft de eenvoudige platte leerlingenlijst
zien, ongewijzigd.
Vervallen (overbodig dankzij drill-down, elke lijst is al kort en gefocust):
het hele inklap-/inspring-mechanisme (group(), openGroups/closedGroups,
editToggle, classHeadRow, applyUserFilter, .am-classhead, .am-indent), het
oude master-detail-paneel (selectedUserKey/syncSelection/renderDetail), en de
generieke "Nieuwe gebruiker"-knop (elke tegel se eigen "+" dekt dit al,
rol+context-correct).
Geen serverwijziging - pure client-herbouw van navigatie/weergave.
Geverifieerd in een echte headless Chromium voor systeemmanager (root +
school + klas + sheet + "+Groepsleiding" koppelt nog echt), schoolbeheerder
(eigen school, geen schoolkiezer/kebab-op-schoolniveau) en groepsleiding
(platte lijst, ongewijzigd).
Was rommelig/te veel niveaus door TE veel verschillende stijlen op dezelfde
pagina: kaarten (Scholen) naast platte rijen (Gebruikers), een teal-getint
klasrijtje, een grijs getint paneel om Scholen - vier stijlen die om
aandacht streden i.p.v. één samenhangend geheel.
- Scholen gebruikt nu dezelfde platte .am-list/.am-row-stijl als de
klassen/gebruikers-boom eronder i.p.v. losse kaarten in een eigen paneel;
het paneel (.am-panel) is weg
- de ingeklapte beheerderslijst per school is weg - die informatie stond al
in Gebruikers (gegroepeerd per school bij "alle scholen"), dubbel tonen
droeg alleen bij aan de herrie
- klasrij heeft geen eigen teal-kader meer (alleen de naam iets zwaarder);
hiërarchie loopt nu via een lichte inspringing (.am-indent) voor
Groepsleiding/Leerlingen en hun rijen/+-knoppen, niet via kleur
- nieuwe editToggle()-helper: gebruikers-, klas- en schoolrijen delen nu
dezelfde "Bewerken"-knop-implementatie i.p.v. drie keer bijna-dezelfde
code, met een eigen openSchoolTools-Set (schoolrol- en klas-id's kunnen
samenvallen met gebruikers-id's)
- geverifieerd in een echte headless Chromium: Scholen en Gebruikers ogen nu
als één systeem, klas-substructuur is duidelijk ingesprongen, en de
bestaande functionaliteit (rename/delete/reset/koppelen) werkt nog
De losse schoolkaarten stonden zonder eigen kader los in de pagina en liepen
zonder duidelijke grens over in de Gebruikers-sectie eronder - verwarrend
omdat dezelfde schoolnaam daar soms letterlijk direct weer opduikt (nu als
groepskop i.p.v. kaart).
- Scholen krijgt een eigen omkaderd paneel (.am-panel) dat alle schoolkaarten
en "+ School" samenbindt tot één zichtbaar geheel
- duidelijke scheidingslijn + meer ruimte vóór de volgende sectiekop, maar
alleen ná een echte sectie (geen ongewenste lijn boven Gebruikers wanneer
Scholen niet getoond wordt, bv. bij een gekozen school)
- geverifieerd in een echte headless Chromium: zowel de "alle scholen"-
weergave (met paneel) als de weergave voor een gekozen school (zonder,
geen regressie)
- klas, Groepsleiding en Leerlingen staan nu letterlijk bij elkaar: elke klas
krijgt een eigen rij (naam + "Bewerken" voor verplaatsen/resetten/
verwijderen, overgenomen uit het oude losse Klassen-paneel) met daaronder
twee eigen sublijstjes - Groepsleiding (leerkrachten gekoppeld aan die
klas) en Leerlingen - elk met een eigen "+"-knop
- "+ Groepsleiding" bij een klas maakt de nieuwe leerkracht niet alleen aan,
maar koppelt die ook meteen aan die klas (hergebruikt de bestaande, al
geteste POST /admin/classes/:id/teachers-route - geen serverwijziging)
- Schoolbeheerder blijft een eigen, vlakke groep los van de klassenboom (ook
als een schoolbeheerder toevallig aan een klas gekoppeld is, om dubbele
vermeldingen te voorkomen); Niet ingedeeld bundelt leerkrachten zonder klas
en leerlingen zonder klas
- renderKlassenPanel is verwijderd (zijn inhoud leeft nu in de klas-tak van
renderGebruikersPanel); de losse "Klassen"-kop in het School-tabblad is weg
- nieuwe openClassTools-Set voor het in-/uitklappen van klasbeheer, apart van
openRows (klas- en gebruiker-id's kunnen samenvallen)
- geverifieerd in een echte headless Chromium: klasrij + twee sublijsten per
klas, Schoolbeheerder/Niet ingedeeld correct gevuld, en "+ Groepsleiding"
koppelt de nieuwe leerkracht daadwerkelijk aan de klas (classIds bevestigd)
- ADMIN_SECTIONS: de drie losse tabbladen zijn samengevoegd tot 1 sectie
("school"); zoeken op een school-, klas- of gebruikersnaam werkt nog
hetzelfde, navigeert nu alleen naar de ene samengevoegde sectie
- nieuwe renderSchoolPanel() zet de drie bestaande, ongewijzigde
deelpanelen (renderScholenPanel/renderKlassenPanel/renderGebruikersPanel)
na elkaar, elk met een eigen kop - geen van de drie is herschreven, alleen
samengesteld, om het risico op regressies te beperken
- rolgedrag blijft exact zoals het was (nu allemaal binnen die ene sectie):
systeemmanager ziet Scholen+Klassen+Gebruikers en de schoolkiezer,
schoolbeheerder ziet Klassen+Gebruikers voor de eigen school (geen
schoolkiezer, geen Scholen-blok), groepsleiding ziet alleen Gebruikers
(geen Klassen-blok) en daarbinnen alleen de leerling-gerelateerde knoppen
- geverifieerd in een echte headless Chromium voor alle drie rollen: juiste
secties, juiste knoppen, juiste zichtbaarheid van de schoolkiezer
Backup van de oude driedelige UI staat als git-tag
ui-before-merged-beheer-v0.4.08 (commit e34bda5).
- db/017: de class_teachers-trigger uit migratie 006 stond alleen 'teacher'
toe en blokkeerde daarmee (met een verwarrende "groepsleiding en klas..."
foutmelding) wat de applicatielaag allang toestond voor schoolbeheerder en
systeemmanager - de trigger is nooit meegegroeid toen die rollen later ook
aan een klas gekoppeld mochten worden. Nu ook admin/super toegestaan,
super school-onafhankelijk zoals de rest van de app dat al behandelt.
- rolwijziging kon een bestaande groepsleiding/schoolbeheerder via een simpel
dropdown-veld naar systeemmanager promoveren, zonder enige bevestiging -
in tegenstelling tot de nieuwe systeemmanager-aanmaak (met wachtwoord-
bevestiging). 'super' is nu geen geldig doel meer voor PATCH .../users/:id
(ook niet via het extraRoles-mechanisme); het rolwijzigingsveld zelf toont
zich niet meer voor een bestaande systeemmanager. Alleen de aparte
aanmaakstap (met bevestiging) kan nog een systeemmanager opleveren.
- meer verticale ruimte tussen rijen in het beheerpaneel (was vrijwel 0),
zodat je niet per ongeluk de verkeerde rij raakt
- de "+ ..."-toevoegknoppen staan nu rechts uitgelijnd i.p.v. links, zodat ze
duidelijker als aparte actie ogen i.p.v. als onderdeel van de lijst
Geverifieerd in een echte headless Chromium: rolwijziging toont voor een
groepsleiding alleen nog teacher/admin als opties.
Een uitgeklapt "+ ..."-formulier (nieuwe schoolbeheerder/leerkracht/leerling/
school/klas) zag er in het beheerpaneel bijna hetzelfde uit als het
bewerkpaneel van een bestaande gebruiker - beide gewoon een rij velden
zonder duidelijk onderscheid.
- .am-add krijgt nu een eigen kader (accentkleur, stippellijn) i.p.v. de
neutrale achtergrond van een gebruikersrij
- het formulier toont bovenaan een titel die herhaalt wát je toevoegt (bv.
"LEERLING"), ook zodra de knoptekst erboven uit beeld is
- de dichtgeklapte "+ ..."-knop zelf krijgt ook de accentkleur, zodat
collapsed en uitgeklapt dezelfde "dit is toevoegen"-taal spreken
- geverifieerd in een echte headless Chromium: duidelijk visueel onderscheid
tussen een toevoegformulier en een echte gebruikersrij
- Onzichtbare knoppen opgelost: .tbtn houdt standaard witte tekst (wit-op-blauw), maar in het beheer staat hij op een lichte achtergrond -> tekst was wit-op-wit. Nu expliciet donkere tekst; de primaire accentknop houdt bewust witte tekst
- Systeemmanager kreeg standaard "alle scholen" waardoor klassen leeg leken en niet toe te voegen waren; er wordt nu meteen een concrete school gekozen (klassen/gebruikers direct gevuld). Contextbalk laat wisselen; "alle scholen" blijft een bewuste keuze
- Lege school toont nu een duidelijke uitleg dat bestaande klassen bij een andere school kunnen horen, met verwijzing naar de schoolkeuze
- Correcte gegevensregels: classes.school_id is NOT NULL met ON DELETE CASCADE, dus een klas kan niet "los" bestaan (die eerdere aanname is teruggedraaid). Een klas is nu te VERPLAATSEN naar een andere school (PATCH weigert null/ongeldig); een verwijderde school neemt zijn klassen mee (cascade) - dat verklaart verdwenen klassen
- Bij een leerling naar een andere school koppelen blijft de klas behouden als die al bij de doelschool hoort
- Verificatie uitgebreid met een echte kleurcontrast-scan (vangt wit-op-wit) over alle secties + de default-school-flow; alle 94 servertests en 8 Playwright-suites groen
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0149FgUQvuwxKKEdvQGmNngF
- Leerlingen stonden onder standaard-ingeklapte klasgroepen, dus met een gekozen school leek de lijst leeg terwijl de detailweergave de juiste school toonde. Klasgroepen staan nu standaard open zodra een school is gekozen (de schoolkeuze wás al het filter); bewust dichtklappen wordt onthouden
- Losse klassen (school verwijderd) waren nergens zichtbaar: de systeemmanager ziet ze nu zonder gekozen school met een uitleg, en kan ze via een School-veld terugkoppelen; nieuwe PATCH /admin/classes/:id + GET ?school=none (super) met servertests
- Bij het aan een school koppelen van een leerling blijft de klasindeling behouden als die klas al bij de doelschool hoort (eerst klas terugkoppelen, dan de leerlingen)
- UI-consistentie: één uniforme control-hoogte (32px) voor álle knoppen, selects en invoervelden in Instellingen - einde aan de grote maatverschillen; T() valt terug op NL en dan de sleutelnaam zodat een knop nooit zonder tekst kan staan
- Status in de gebruikerstabel als compacte glyph (● in gebruik / ○ wacht) met uitleg bij aanwijzen i.p.v. een afgekapte "nog niet ing…"-chip
- Geverifieerd in headless Chromium: nieuwe suite (21 checks: zichtbaarheid met schoolfilter, losse klassen, geen lege knoppen, uniforme hoogte over 8 secties) + volledige regressie van 5 bestaande suites
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0149FgUQvuwxKKEdvQGmNngF