Voeg thematische kleurplaten en creatieve niveaus toe (v0.4.65-beta) #3
9 changed files with 174 additions and 24 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
0.4.37-beta
|
||||
0.4.38-beta
|
||||
|
|
|
|||
|
|
@ -637,6 +637,19 @@
|
|||
.st-sec-title{font-size:17px; font-weight:800;}
|
||||
.st-sec-sub{font-size:12.5px; color:var(--muted); margin-top:2px;}
|
||||
/* curriculumwiki: volwassen, informatief en bruikbaar op tablet/telefoon */
|
||||
|
||||
.wiki-goal-focus{outline:3px solid var(--accent);outline-offset:3px;animation:wikiFocus 1.4s ease-out}
|
||||
@keyframes wikiFocus{from{background:var(--accent-soft)}to{background:var(--surface)}}
|
||||
.winfo[hidden]{display:none}\n .widget-curriculum-modal{width:min(620px,94vw);max-height:min(760px,88vh);overflow:auto}
|
||||
.widget-curriculum-head{display:flex;align-items:center;gap:12px;margin-bottom:8px}
|
||||
.widget-curriculum-head h2{flex:1;margin:0;font-size:20px}
|
||||
.widget-curriculum-goals{display:flex;flex-direction:column;gap:8px;margin:14px 0}
|
||||
.widget-curriculum-goal{display:flex;flex-direction:column;gap:4px;padding:11px 12px;border:1px solid var(--line);border-radius:12px;background:var(--surface-2);color:var(--ink);text-decoration:none}
|
||||
.widget-curriculum-goal:hover,.widget-curriculum-goal:focus-visible{border-color:var(--accent);outline:2px solid var(--accent-soft)}
|
||||
.widget-curriculum-goal span{font-size:13px;line-height:1.4}.widget-curriculum-goal small{color:var(--accent-ink);font-weight:750}
|
||||
.widget-curriculum-empty,.widget-curriculum-careful{padding:10px 12px;border-radius:10px;background:var(--surface-2);font-size:13px;line-height:1.45}
|
||||
.widget-curriculum-careful{color:var(--muted)}.widget-curriculum-all{display:inline-flex;text-decoration:none}
|
||||
|
||||
#curriculumWiki{display:flex;flex-direction:column;gap:14px;padding-bottom:10px;}
|
||||
.wiki-hero{display:flex;align-items:flex-start;justify-content:space-between;gap:18px;padding:18px;border:1px solid var(--line);border-radius:12px;background:linear-gradient(135deg,var(--surface),var(--surface-2));}
|
||||
.wiki-hero-text{max-width:680px}.wiki-kicker{margin-bottom:5px;color:var(--accent);font-size:11px;font-weight:750;letter-spacing:.6px;text-transform:uppercase}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@
|
|||
<button class="tbtn ghost" id="btnFolders">📁</button>
|
||||
<button class="tbtn ghost" id="btnSave">💾 <span data-i18n="saveBoard"></span></button>
|
||||
<button class="tbtn ghost" id="btnCast" title="Cast">📡</button>
|
||||
<button class="tbtn ghost" id="btnWiki" style="display:none;">📚 <span data-i18n="wikiShort"></span></button>
|
||||
<button class="tbtn ghost" id="btnUser">⚙️ <span id="userLbl"></span></button>
|
||||
<button class="tbtn ghost" id="btnFs" title="Fullscreen">⛶</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -95,6 +95,92 @@ function clampWidgetSize(w, h, def){
|
|||
blijft vinden ook als er widgets vóór/na worden toegevoegd of verplaatst */
|
||||
function genWidgetId(){ return "w" + Date.now().toString(36) + Math.random().toString(36).slice(2,8); }
|
||||
|
||||
function curriculumGoalsForWidget(widgetId){
|
||||
const matches=[];
|
||||
CURRICULUM_PO_2026.areas.forEach(area=>area.goals.forEach(goal=>{
|
||||
if(goal.widgets.includes(widgetId))matches.push({area,goal});
|
||||
}));
|
||||
return matches;
|
||||
}
|
||||
let widgetCurriculumWrap=null;
|
||||
function closeWidgetCurriculumInfo(){
|
||||
if(widgetCurriculumWrap)widgetCurriculumWrap.classList.remove("open");
|
||||
}
|
||||
function openWidgetCurriculumInfo(def){
|
||||
if(!currentUser||!can("curriculum.view"))return;
|
||||
if(!widgetCurriculumWrap){
|
||||
widgetCurriculumWrap=document.createElement("div");
|
||||
widgetCurriculumWrap.className="modalwrap";
|
||||
widgetCurriculumWrap.id="widgetCurriculumWrap";
|
||||
widgetCurriculumWrap.setAttribute("role","dialog");
|
||||
widgetCurriculumWrap.setAttribute("aria-modal","true");
|
||||
widgetCurriculumWrap.addEventListener("click",event=>{
|
||||
if(event.target===widgetCurriculumWrap)closeWidgetCurriculumInfo();
|
||||
});
|
||||
document.body.appendChild(widgetCurriculumWrap);
|
||||
}
|
||||
const panel=document.createElement("div");
|
||||
panel.className="modal widget-curriculum-modal";
|
||||
const head=document.createElement("div");
|
||||
head.className="widget-curriculum-head";
|
||||
const title=document.createElement("h2");
|
||||
title.id="widgetCurriculumTitle";
|
||||
title.textContent=def.icon+" "+T("wg_"+def.id);
|
||||
const close=document.createElement("button");
|
||||
close.type="button";close.className="wclose";close.textContent="✕";
|
||||
close.title=T("close");close.setAttribute("aria-label",T("close"));
|
||||
close.addEventListener("click",closeWidgetCurriculumInfo);
|
||||
head.append(title,close);panel.appendChild(head);
|
||||
panel.appendChild(document.createTextNode(T("widgetCurriculumIntro")));
|
||||
const goals=curriculumGoalsForWidget(def.id);
|
||||
if(goals.length){
|
||||
const list=document.createElement("div");
|
||||
list.className="widget-curriculum-goals";
|
||||
goals.forEach(({area,goal})=>{
|
||||
const link=document.createElement("a");
|
||||
link.className="widget-curriculum-goal";
|
||||
link.href="#wiki-goal-"+goal.id;
|
||||
const label=document.createElement("strong");
|
||||
label.textContent=area.icon+" "+T("wikiGoal")+" "+goal.id+" · "+area.title;
|
||||
const summary=document.createElement("span");
|
||||
summary.textContent=goal.summary;
|
||||
const status=document.createElement("small");
|
||||
status.textContent=T(goal.coverage==="partial"?"wikiCoveragePartial":goal.coverage==="support"?"wikiCoverageSupport":"wikiCoverageOpen")+" · "+T("widgetCurriculumWiki");
|
||||
link.append(label,summary,status);
|
||||
link.addEventListener("click",event=>{
|
||||
event.preventDefault();closeWidgetCurriculumInfo();
|
||||
openSettings("curriculum",{area:area.id,goal:goal.id});
|
||||
});
|
||||
list.appendChild(link);
|
||||
});
|
||||
panel.appendChild(list);
|
||||
}else{
|
||||
const empty=document.createElement("p");
|
||||
empty.className="widget-curriculum-empty";
|
||||
empty.textContent=T("widgetCurriculumNone");
|
||||
panel.appendChild(empty);
|
||||
}
|
||||
const careful=document.createElement("p");
|
||||
careful.className="widget-curriculum-careful";
|
||||
careful.textContent=T("widgetCurriculumCareful");
|
||||
panel.appendChild(careful);
|
||||
const all=document.createElement("a");
|
||||
all.className="tbtn widget-curriculum-all";
|
||||
all.href="#curriculum";
|
||||
all.textContent=T("widgetCurriculumAll");
|
||||
all.addEventListener("click",event=>{
|
||||
event.preventDefault();closeWidgetCurriculumInfo();openSettings("curriculum");
|
||||
});
|
||||
panel.appendChild(all);
|
||||
widgetCurriculumWrap.setAttribute("aria-labelledby",title.id);
|
||||
widgetCurriculumWrap.replaceChildren(panel);
|
||||
widgetCurriculumWrap.classList.add("open");
|
||||
close.focus();
|
||||
}
|
||||
document.addEventListener("userchange",()=>{
|
||||
if(!currentUser||!can("curriculum.view"))closeWidgetCurriculumInfo();
|
||||
});
|
||||
|
||||
function makeWidget(def, saved){
|
||||
const win = document.createElement("div");
|
||||
win.className = "widget";
|
||||
|
|
@ -117,6 +203,10 @@ function makeWidget(def, saved){
|
|||
const head = document.createElement("div");
|
||||
head.className = "widget-head";
|
||||
head.innerHTML = `<span class="wicon">${def.icon}</span><span class="wtitle"></span>`;
|
||||
const infoBtn = document.createElement("button");
|
||||
infoBtn.className="wmin winfo";infoBtn.type="button";infoBtn.textContent="ⓘ";infoBtn.hidden=true;
|
||||
infoBtn.addEventListener("click",event=>{event.stopPropagation();openWidgetCurriculumInfo(def);});
|
||||
head.appendChild(infoBtn);
|
||||
const dupBtn = document.createElement("button"); dupBtn.className="wmin wdup"; dupBtn.textContent="⧉"; head.appendChild(dupBtn);
|
||||
const lockBtn = document.createElement("button"); lockBtn.className="wmin wlock"; lockBtn.textContent="🔓"; head.appendChild(lockBtn);
|
||||
const previewBtn = document.createElement("button"); previewBtn.className="wmin wpreview"; previewBtn.textContent="◉"; head.appendChild(previewBtn);
|
||||
|
|
@ -227,7 +317,7 @@ function makeWidget(def, saved){
|
|||
}
|
||||
maxBtn.addEventListener("click", ()=>{ setMax(win.dataset.max!=="1"); markBoardChange(); });
|
||||
head.addEventListener("dblclick", e=>{
|
||||
if(e.target===close || e.target===minBtn || e.target===maxBtn) return;
|
||||
if(e.target.closest("button")) return;
|
||||
setMin(true);
|
||||
});
|
||||
|
||||
|
|
@ -236,14 +326,18 @@ function makeWidget(def, saved){
|
|||
minBtn.title = T("wMin");
|
||||
maxBtn.title = T(win.dataset.max==="1" ? "wUnfull" : "wFull");
|
||||
zBtn.title = T("wZoom");
|
||||
infoBtn.title = T("widgetCurriculumInfo");
|
||||
infoBtn.setAttribute("aria-label",infoBtn.title);
|
||||
if(pill){
|
||||
pill.querySelector(".dl").textContent = T("wg_"+def.id);
|
||||
pill.title = T("wMax");
|
||||
pill.querySelector(".dock-close").title = T("close");
|
||||
}
|
||||
};
|
||||
setTitle();
|
||||
const setCurriculumInfoVisibility=()=>{infoBtn.hidden=!(currentUser&&can("curriculum.view"));};
|
||||
setTitle();setCurriculumInfoVisibility();
|
||||
document.addEventListener("langchange", setTitle);
|
||||
document.addEventListener("userchange",setCurriculumInfoVisibility);
|
||||
|
||||
win.addEventListener("pointerdown", ()=>{ win.style.zIndex = ++zTop; });
|
||||
head.addEventListener("pointerdown", e=>{
|
||||
|
|
@ -271,6 +365,8 @@ function makeWidget(def, saved){
|
|||
function removeWidget(){
|
||||
markBoardChange();
|
||||
if(pill){ pill.remove(); pill = null; }
|
||||
document.removeEventListener("langchange",setTitle);
|
||||
document.removeEventListener("userchange",setCurriculumInfoVisibility);
|
||||
instances.delete(inst); win.remove(); updateEmptyHint();
|
||||
}
|
||||
close.addEventListener("click", removeWidget);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"use strict";
|
||||
/* 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. */
|
||||
const VERSION = "0.4.37-beta";
|
||||
const VERSION = "0.4.38-beta";
|
||||
(function(){
|
||||
const tag = document.getElementById("verTag");
|
||||
tag.textContent = "v"+VERSION;
|
||||
|
|
@ -234,7 +234,7 @@ const I18N = {
|
|||
stGroupPersonal:"Persoonlijk", stGroupSchool:"School", stGroupSystem:"Systeem",
|
||||
stAccountSub:"Je gegevens, wachtwoord en reservekopieën.",
|
||||
stViewSub:"Weergave op dit apparaat: thema, taal en menubalk.",
|
||||
wikiTitle:"Curriculumwiki", wikiShort:"Wiki",
|
||||
wikiTitle:"Curriculumwiki",
|
||||
wikiSub:"Nieuwe SLO-kerndoelen voor het primair onderwijs, per leergebied.",
|
||||
wikiKicker:"Primair onderwijs · juli 2026",
|
||||
wikiIntro:"Bekijk de 40 nieuwe kerndoelen, hun onderdelen en de huidige aansluiting van Teach.",
|
||||
|
|
@ -254,6 +254,10 @@ const I18N = {
|
|||
wikiWidgets:"Huidige widgets", wikiNoResults:"Geen kerndoelen gevonden.",
|
||||
wikiCarefulTitle:"Zorgvuldig gebruiken.",
|
||||
wikiCarefulText:"Een widget die één onderdeel oefent, dekt niet automatisch het volledige kerndoel. School- en ervaringsdoelen vragen andere vormen van bewijs dan een goed/fout-score.",
|
||||
widgetCurriculumInfo:"Kerndoelinformatie", widgetCurriculumIntro:"Deze widget draagt bij aan de onderstaande kerndoelen.",
|
||||
widgetCurriculumNone:"Voor deze ondersteunende widget is geen directe koppeling met een kerndoel vastgesteld.",
|
||||
widgetCurriculumWiki:"Bekijk dit kerndoel in de curriculumwiki", widgetCurriculumAll:"Open de volledige curriculumwiki",
|
||||
widgetCurriculumCareful:"Een widget ondersteunt onderdelen van een kerndoel en vormt op zichzelf geen bewijs dat het volledige doel is behaald.",
|
||||
wikiLanguageNote:"The official SLO goals and these implementation summaries are shown in Dutch.",
|
||||
stUsersSub:"Accounts beheren: leerlingen, staf, ouders en aanmeldingen.",
|
||||
stKlassenSub:"Klassen aanmaken, koppelen en beheren.",
|
||||
|
|
@ -603,7 +607,7 @@ const I18N = {
|
|||
stGroupPersonal:"Personal", stGroupSchool:"School", stGroupSystem:"System",
|
||||
stAccountSub:"Your details, password and backups.",
|
||||
stViewSub:"Display on this device: theme, language and toolbar.",
|
||||
wikiTitle:"Curriculum wiki", wikiShort:"Wiki",
|
||||
wikiTitle:"Curriculum wiki",
|
||||
wikiSub:"New SLO attainment targets for Dutch primary education, grouped by learning area.",
|
||||
wikiKicker:"Primary education · July 2026",
|
||||
wikiIntro:"Browse all 40 new attainment targets, their components and Teach's current coverage.",
|
||||
|
|
@ -623,6 +627,10 @@ const I18N = {
|
|||
wikiWidgets:"Current widgets", wikiNoResults:"No attainment targets found.",
|
||||
wikiCarefulTitle:"Use with care.",
|
||||
wikiCarefulText:"A widget practising one component does not automatically cover the full target. School-level and experience targets require different evidence from a right/wrong score.",
|
||||
widgetCurriculumInfo:"Attainment target information", widgetCurriculumIntro:"This widget contributes to the attainment targets below.",
|
||||
widgetCurriculumNone:"No direct attainment-target link has been established for this supporting widget.",
|
||||
widgetCurriculumWiki:"View this target in the curriculum wiki", widgetCurriculumAll:"Open the complete curriculum wiki",
|
||||
widgetCurriculumCareful:"A widget supports parts of a target and is not, by itself, evidence that the full target has been achieved.",
|
||||
wikiLanguageNote:"The official SLO goals and these implementation summaries are shown in Dutch.",
|
||||
stUsersSub:"Manage accounts: pupils, staff, parents and enrolments.",
|
||||
stKlassenSub:"Create, link and manage classes.",
|
||||
|
|
@ -1011,7 +1019,6 @@ const roleKey = r => r==="super" ? "roleSuper" : r==="admin" ? "roleAdmin" : r==
|
|||
function updateUserUI(){
|
||||
document.getElementById("userLbl").textContent = currentUser ? currentUser.displayName : T("login");
|
||||
document.getElementById("btnUser").classList.toggle("on", !!currentUser);
|
||||
document.getElementById("btnWiki").style.display = can("curriculum.view") ? "" : "none";
|
||||
/* welke instellingen-secties zichtbaar zijn bepaalt settings.js per rol
|
||||
(sectieregister); hier alleen nog de accountgegevens zelf */
|
||||
if(currentUser){
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ const CURRICULUM_PO_2026=Object.freeze({
|
|||
id:"rekenen-en-wiskunde",icon:"🔢",title:"Rekenen en wiskunde",goalsRange:"10–18",page:32,
|
||||
description:"Wiskundige concepten, denk-werkwijzen, taal en gereedschap begrijpen en toepassen in de wereld.",
|
||||
goals:[
|
||||
{id:10,domain:"Wiskundige concepten",summary:"Leerlingen redeneren en rekenen met getallen, breuken en verhoudingen.",parts:["Gehele en decimale getallen","Breuken","Verhoudingen"],coverage:"partial",widgets:["madd","msub","mmul","mdiv","mpct","numberline","fractions","placevalue"]},
|
||||
{id:11,domain:"Wiskundige concepten",summary:"Leerlingen meten, redeneren en rekenen met grootheden, eenheden en passende meetinstrumenten.",parts:["Grootheden en eenheden"],coverage:"partial",widgets:["clock","money"]},
|
||||
{id:10,domain:"Wiskundige concepten",summary:"Leerlingen redeneren en rekenen met getallen, breuken en verhoudingen.",parts:["Gehele en decimale getallen","Breuken","Verhoudingen"],coverage:"partial",widgets:["madd","msub","mmul","mdiv","mpct","numberline","fractions","placevalue","dice"]},
|
||||
{id:11,domain:"Wiskundige concepten",summary:"Leerlingen meten, redeneren en rekenen met grootheden, eenheden en passende meetinstrumenten.",parts:["Grootheden en eenheden"],coverage:"partial",widgets:["clock","money","timer","schedule"]},
|
||||
{id:12,domain:"Wiskundige concepten",summary:"Leerlingen representeren en interpreteren data en beoordelen conclusies bij gegevens kritisch.",parts:["Data"],coverage:"support",widgets:["poll"]},
|
||||
{id:13,domain:"Wiskundige concepten",summary:"Leerlingen herkennen, beschrijven en onderzoeken patronen en verbanden.",parts:["Patronen en verbanden"],coverage:"open",widgets:[]},
|
||||
{id:14,domain:"Wiskundige concepten",summary:"Leerlingen redeneren over meetkundige figuren en plaatsbepaling en voeren transformaties uit.",parts:["Meetkunde"],coverage:"open",widgets:[]},
|
||||
|
|
@ -74,7 +74,7 @@ const CURRICULUM_PO_2026=Object.freeze({
|
|||
description:"Natuurwetenschap, technologie, organismen, gezondheid en systeem aarde onderzoekend leren begrijpen.",
|
||||
goals:[
|
||||
{id:29,domain:"Natuurwetenschappen en technologie",summary:"Leerlingen onderzoeken vraagstukken met natuurwetenschappelijke en technologische denk- en werkwijzen.",parts:["Vraagstukken","Denkwijzen","Werkwijzen","Aard van natuurwetenschappen en technologie"],coverage:"partial",widgets:["trees","birds","plants"]},
|
||||
{id:30,domain:"Natuur- en scheikunde en technische systemen",summary:"Leerlingen onderzoeken technische systemen, stoffen en verschijnselen rond licht, geluid, energie en krachten.",parts:["Technische systemen","Stoffen en hun eigenschappen","Licht, geluid, energie en krachten"],coverage:"open",widgets:[]},
|
||||
{id:30,domain:"Natuur- en scheikunde en technische systemen",summary:"Leerlingen onderzoeken technische systemen, stoffen en verschijnselen rond licht, geluid, energie en krachten.",parts:["Technische systemen","Stoffen en hun eigenschappen","Licht, geluid, energie en krachten"],coverage:"support",widgets:["noise"]},
|
||||
{id:31,domain:"Organismen en gezondheid",summary:"Leerlingen onderzoeken organismen en hun levensprocessen en leren onderbouwde keuzes rond lichamelijke en mentale gezondheid.",parts:["Organismen","Gezond leven"],coverage:"partial",widgets:["trees","birds","plants","breathe","mood","feelings"]},
|
||||
{id:32,domain:"Systeem aarde",summary:"Leerlingen onderzoeken de aarde, weer, klimaat, water en samenhang en menselijke invloed in ecosystemen.",parts:["Aarde","Weer, klimaat en water","Ecosystemen"],coverage:"partial",widgets:["trees","birds","plants","topography"]}
|
||||
]
|
||||
|
|
@ -91,8 +91,8 @@ const CURRICULUM_PO_2026=Object.freeze({
|
|||
id:"kunst-en-cultuur",icon:"🎨",title:"Kunst en cultuur",goalsRange:"35–37",page:92,
|
||||
description:"Artistiek creatief vermogen ontwikkelen, kunstzinnige uitingen maken en kunst en cultuur beleven en duiden.",
|
||||
goals:[
|
||||
{id:35,domain:"Artistiek creatief vermogen",summary:"Leerlingen gebruiken creatieve strategieën in een iteratief proces en geven betekenis aan eigen en andermans werk.",parts:["Creatieve maak- en denkstrategieën","Ontwikkelen van creatieve vermogens","Betekenis geven"],coverage:"support",widgets:["write","mind","media"]},
|
||||
{id:36,domain:"Maken en betekenis geven",summary:"Leerlingen verbeelden ideeën en gebruiken technieken, vaardigheden, materialen en vaktaal uit verschillende kunstdisciplines.",parts:["Verbeelden en creëren","Kunstzinnige technieken en vaardigheden"],coverage:"support",widgets:["write","media"]},
|
||||
{id:35,domain:"Artistiek creatief vermogen",summary:"Leerlingen gebruiken creatieve strategieën in een iteratief proces en geven betekenis aan eigen en andermans werk.",parts:["Creatieve maak- en denkstrategieën","Ontwikkelen van creatieve vermogens","Betekenis geven"],coverage:"support",widgets:["write","mind","media","birthday","avatar"]},
|
||||
{id:36,domain:"Maken en betekenis geven",summary:"Leerlingen verbeelden ideeën en gebruiken technieken, vaardigheden, materialen en vaktaal uit verschillende kunstdisciplines.",parts:["Verbeelden en creëren","Kunstzinnige technieken en vaardigheden"],coverage:"support",widgets:["write","media","birthday","avatar"]},
|
||||
{id:37,domain:"Meemaken en betekenis geven",summary:"Leerlingen beleven kunst en cultuur actief en verbinden uitingen aan maker, tijd, plaats, functie en context.",parts:["Kunst en cultuur actief meemaken","Kunst en cultuur in context"],coverage:"open",widgets:[]}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -148,13 +148,13 @@ function registerSettingsSection(sec){ ST_SECTIONS.push(sec); }
|
|||
});
|
||||
|
||||
/* ---- openen ---------------------------------------------------------------- */
|
||||
window.openSettings = function(section){
|
||||
window.openSettings = function(section, payload){
|
||||
const msg = document.getElementById("settingsMsg");
|
||||
msg.textContent = ""; msg.classList.remove("ok");
|
||||
searchInp.value = "";
|
||||
searchInp.placeholder = T("stSearchPh");
|
||||
buildNav();
|
||||
goSection(section || (currentUser ? "account" : "view"));
|
||||
goSection(section || (currentUser ? "account" : "view"), payload);
|
||||
/* beheerdata alvast op de achtergrond laden zodat zoeken op namen van
|
||||
gebruikers/klassen/scholen meteen wat oplevert (admin.js bewaakt zelf
|
||||
dat er maar één keer geladen wordt) */
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
(function(){
|
||||
const root=document.getElementById("curriculumWiki");
|
||||
const wikiButton=document.getElementById("btnWiki");
|
||||
let selectedArea="all";
|
||||
let query="";
|
||||
|
||||
|
|
@ -57,6 +56,7 @@
|
|||
const grid=node("div","wiki-grid");
|
||||
goals.forEach(goal=>{
|
||||
const card=node("article","wiki-goal");
|
||||
card.id="wiki-goal-"+goal.id;
|
||||
const head=node("div","wiki-goal-head");
|
||||
head.appendChild(node("span","wiki-goal-id",T("wikiGoal")+" "+goal.id));
|
||||
head.appendChild(node("span","wiki-domain",goal.domain));
|
||||
|
|
@ -94,7 +94,7 @@
|
|||
}
|
||||
|
||||
function renderCurriculumWiki(payload){
|
||||
if(payload&&payload.area)selectedArea=payload.area;
|
||||
if(payload&&payload.area){selectedArea=payload.area;query="";}
|
||||
root.replaceChildren();
|
||||
const header=node("div","wiki-hero");
|
||||
const heroText=node("div","wiki-hero-text");
|
||||
|
|
@ -169,6 +169,10 @@
|
|||
drawGoals(holder,filters);
|
||||
});
|
||||
drawGoals(holder,filters);
|
||||
if(payload&&payload.goal)requestAnimationFrame(()=>{
|
||||
const target=document.getElementById("wiki-goal-"+payload.goal);
|
||||
if(target){target.classList.add("wiki-goal-focus");target.scrollIntoView({block:"center"});}
|
||||
});
|
||||
|
||||
const disclaimer=node("footer","wiki-disclaimer");
|
||||
disclaimer.appendChild(node("strong",null,T("wikiCarefulTitle")));
|
||||
|
|
@ -198,5 +202,4 @@
|
|||
}
|
||||
});
|
||||
|
||||
wikiButton.addEventListener("click",()=>openSettings("curriculum"));
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -27,16 +27,48 @@ test('curriculumdataset bevat negen leergebieden en alle veertig kerndoelen',asy
|
|||
}
|
||||
});
|
||||
|
||||
test('curriculumwiki is alleen zichtbaar voor alle volwassen rollen',async()=>{
|
||||
test('iedere kerndoelkoppeling verwijst naar een bestaande widget en de informatieknop linkt diep naar de wiki',async()=>{
|
||||
const [curriculumSource,board,settings,wiki,css]=await Promise.all([
|
||||
readFile('public/js/curriculum.js','utf8'),
|
||||
readFile('public/js/board.js','utf8'),
|
||||
readFile('public/js/settings.js','utf8'),
|
||||
readFile('public/js/wiki.js','utf8'),
|
||||
readFile('public/css/teach.css','utf8')
|
||||
]);
|
||||
const context={};
|
||||
runInNewContext(curriculumSource+';globalThis.__curriculum=CURRICULUM_PO_2026',context);
|
||||
const data=JSON.parse(JSON.stringify(context.__curriculum));
|
||||
const registered=new Set([...board.matchAll(/\{\s*id:"([^"]+)"\s*,\s*cat:/g)].map(match=>match[1]));
|
||||
const linked=new Set(data.areas.flatMap(area=>area.goals.flatMap(goal=>goal.widgets)));
|
||||
for(const widget of linked)assert.ok(registered.has(widget),widget+' is gekoppeld maar niet geregistreerd');
|
||||
for(const widget of ['letters','sentence','madd','fractions','dice','timer','schedule','trees','topography','noise','birthday','avatar']){
|
||||
assert.ok(linked.has(widget),widget+' mist een inhoudelijke kerndoelkoppeling');
|
||||
}
|
||||
assert.match(board,/function curriculumGoalsForWidget/);
|
||||
assert.match(board,/link\.href="#wiki-goal-"\+goal\.id/);
|
||||
assert.match(board,/openSettings\("curriculum",\{area:area\.id,goal:goal\.id\}\)/);
|
||||
assert.match(settings,/window\.openSettings = function\(section, payload\)/);
|
||||
assert.match(wiki,/card\.id="wiki-goal-"\+goal\.id/);
|
||||
assert.match(wiki,/target\.scrollIntoView\(\{block:"center"\}\)/);
|
||||
assert.match(css,/\.winfo\[hidden\]\{display:none\}/);
|
||||
assert.match(css,/\.widget-curriculum-modal/);
|
||||
});
|
||||
|
||||
test('curriculumwiki en widgetinformatie zijn alleen zichtbaar voor volwassen rollen',async()=>{
|
||||
assert.deepEqual(PERMISSIONS['curriculum.view'],['super','admin','teacher','parent']);
|
||||
assert.ok(!PERMISSIONS['curriculum.view'].includes('pupil'));
|
||||
const [client,wiki]=await Promise.all([
|
||||
const [client,wiki,board,html]=await Promise.all([
|
||||
readFile('public/js/permissions.js','utf8'),
|
||||
readFile('public/js/wiki.js','utf8')
|
||||
readFile('public/js/wiki.js','utf8'),
|
||||
readFile('public/js/board.js','utf8'),
|
||||
readFile('public/index.html','utf8')
|
||||
]);
|
||||
assert.match(client,/'curriculum\.view':\s*\['super', 'admin', 'teacher', 'parent'\]/);
|
||||
assert.match(wiki,/visible:\(\)=>!!currentUser&&can\("curriculum\.view"\)/);
|
||||
assert.match(wiki,/wikiButton\.addEventListener\("click",\(\)=>openSettings\("curriculum"\)\)/);
|
||||
assert.match(board,/infoBtn\.hidden=!\(currentUser&&can\("curriculum\.view"\)\)/);
|
||||
assert.match(board,/if\(!currentUser\|\|!can\("curriculum\.view"\)\)return/);
|
||||
assert.doesNotMatch(html,/id="btnWiki"/);
|
||||
assert.doesNotMatch(wiki,/wikiButton/);
|
||||
assert.doesNotMatch(wiki,/innerHTML\s*=/);
|
||||
});
|
||||
|
||||
|
|
@ -51,7 +83,7 @@ test('curriculumwiki is geladen, doorzoekbaar, responsief en tweetalig bediend',
|
|||
assert.ok(html.indexOf('js/settings.js')<html.indexOf('js/curriculum.js'));
|
||||
assert.ok(html.indexOf('js/curriculum.js')<html.indexOf('js/wiki.js'));
|
||||
assert.ok(html.indexOf('js/wiki.js')<html.indexOf('js/app.js'));
|
||||
assert.match(html,/id="btnWiki"[^>]*display:none/);
|
||||
assert.doesNotMatch(html,/id="btnWiki"/);
|
||||
assert.match(html,/data-section="curriculum"/);
|
||||
assert.match(wiki,/input\.type="search"/);
|
||||
assert.match(wiki,/dataset\.area/);
|
||||
|
|
@ -60,6 +92,6 @@ test('curriculumwiki is geladen, doorzoekbaar, responsief en tweetalig bediend',
|
|||
}
|
||||
assert.match(css,/\.wiki-grid\{[^}]*grid-template-columns:repeat\(2/);
|
||||
assert.match(css,/@media \(max-width:720px\)[\s\S]*?\.wiki-grid\{grid-template-columns:1fr\}/);
|
||||
assert.ok(core.includes('document.getElementById("btnWiki").style.display = can("curriculum.view")'));
|
||||
assert.doesNotMatch(core,/btnWiki/);
|
||||
assert.ok(core.includes('const VERSION = "'+version.trim()+'"'));
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue