All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 53s
188 lines
7.3 KiB
JavaScript
188 lines
7.3 KiB
JavaScript
/* teach - veilige rolvoorbeeldweergave voor systeemmanagers.
|
||
Alleen de clientinterface en zichtbare menu's veranderen. De sessiecookie,
|
||
currentUser en serverautorisatie blijven altijd van de systeemmanager. */
|
||
"use strict";
|
||
|
||
(function(){
|
||
const roleRow=document.getElementById("superViewRole");
|
||
const roleSeg=document.getElementById("segViewRole");
|
||
const banner=document.getElementById("rolePreviewBanner");
|
||
const bannerLabel=document.getElementById("rolePreviewLabel");
|
||
const resetButton=banner.querySelector("button");
|
||
const ROLE_KEYS={
|
||
super:"vwRoleSystem",admin:"vwRoleAdmin",teacher:"vwRoleTeacher",
|
||
parent:"vwRoleParent",pupil:"vwRolePupil"
|
||
};
|
||
let renderSequence=0;
|
||
let pupilWidgetPicker=null;
|
||
|
||
function closePupilWidgetPicker(){
|
||
if(pupilWidgetPicker)pupilWidgetPicker.classList.remove("open");
|
||
}
|
||
function openPupilWidgetPicker(){
|
||
if(!isSystemManager()||activeRole()!=="pupil")return;
|
||
if(!pupilWidgetPicker){
|
||
pupilWidgetPicker=document.createElement("div");
|
||
pupilWidgetPicker.className="modalwrap";
|
||
pupilWidgetPicker.id="pupilPreviewWidgetPicker";
|
||
pupilWidgetPicker.setAttribute("role","dialog");
|
||
pupilWidgetPicker.setAttribute("aria-modal","true");
|
||
pupilWidgetPicker.addEventListener("click",event=>{
|
||
if(event.target===pupilWidgetPicker)closePupilWidgetPicker();
|
||
});
|
||
document.body.appendChild(pupilWidgetPicker);
|
||
}
|
||
const modal=document.createElement("div");
|
||
modal.className="modal role-preview-widget-picker";
|
||
const head=document.createElement("div");
|
||
head.className="gallery-head";
|
||
const title=document.createElement("h2");
|
||
title.id="pupilPreviewWidgetTitle";
|
||
title.textContent=T("vwPupilChooseWidget");
|
||
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",closePupilWidgetPicker);
|
||
head.append(title,close);modal.appendChild(head);
|
||
const note=document.createElement("p");
|
||
note.className="guestnote";note.textContent=T("vwPupilAddWidgetNote");
|
||
modal.appendChild(note);
|
||
const host=document.createElement("div");
|
||
pupilAllowedDefs().forEach(def=>{
|
||
const card=document.createElement("button");
|
||
card.type="button";card.className="gcard role-preview-widget-card";
|
||
const icon=document.createElement("span");
|
||
icon.className="gi";icon.textContent=def.icon;
|
||
const text=document.createElement("span");
|
||
const name=document.createElement("strong");
|
||
name.className="gn";name.textContent=T("wg_"+def.id);
|
||
const desc=document.createElement("small");
|
||
desc.className="gd";desc.textContent=T("wg_"+def.id+"_d");
|
||
text.append(name,desc);card.append(icon,text);
|
||
card.addEventListener("click",()=>addPupilPreviewWidget(def));
|
||
host.appendChild(card);
|
||
});
|
||
host.className="role-preview-widget-grid";
|
||
modal.appendChild(host);
|
||
pupilWidgetPicker.setAttribute("aria-labelledby",title.id);
|
||
pupilWidgetPicker.replaceChildren(modal);
|
||
pupilWidgetPicker.classList.add("open");
|
||
close.focus();
|
||
}
|
||
async function addPupilPreviewWidget(def){
|
||
if(!isSystemManager()||activeRole()!=="pupil"||!pupilAllowedDefs().includes(def))return;
|
||
closePupilWidgetPicker();
|
||
const previewRole=activeRole();
|
||
document.body.classList.add("role-preview-updating");
|
||
stopPupilView();
|
||
setActiveViewRole("super");
|
||
try{
|
||
makeWidget(def);
|
||
await doSave();
|
||
}finally{
|
||
setActiveViewRole(previewRole);
|
||
document.body.classList.remove("role-preview-updating");
|
||
renderPreviewSurface();
|
||
}
|
||
}
|
||
|
||
|
||
const isSystemManager=()=>!!currentUser&¤tUser.role==="super";
|
||
const roleLabel=role=>T(ROLE_KEYS[role]||ROLE_KEYS.super);
|
||
|
||
function storedRole(){
|
||
try{
|
||
const value=localStorage.getItem("teach.superViewRole");
|
||
return VIEW_ROLES.includes(value)?value:"super";
|
||
}catch(e){return"super";}
|
||
}
|
||
function storeRole(role){
|
||
try{localStorage.setItem("teach.superViewRole",role);}catch(e){}
|
||
}
|
||
function previewNotice(text){
|
||
const note=document.createElement("aside");
|
||
note.className="role-preview-note";
|
||
const strong=document.createElement("strong");
|
||
strong.textContent=T("vwPreview")+": ";
|
||
note.append(strong,document.createTextNode(text));
|
||
return note;
|
||
}
|
||
function clearPreviewSurface(){
|
||
renderSequence++;
|
||
document.body.classList.remove("role-preview-active","role-preview-parent","role-preview-pupil");
|
||
banner.hidden=true;
|
||
closePupilWidgetPicker();
|
||
if(isSystemManager()){
|
||
stopPupilView();
|
||
stopParentView();
|
||
}
|
||
}
|
||
function syncControls(){
|
||
const enabled=isSystemManager();
|
||
roleRow.hidden=!enabled;
|
||
const role=enabled?activeRole():"super";
|
||
roleSeg.querySelectorAll("button").forEach(button=>{
|
||
const selected=button.dataset.role===role;
|
||
button.classList.toggle("active",selected);
|
||
button.setAttribute("aria-pressed",String(selected));
|
||
});
|
||
banner.hidden=!enabled||role==="super";
|
||
bannerLabel.textContent=enabled&&role!=="super"?roleLabel(role):"";
|
||
}
|
||
async function renderPreviewSurface(){
|
||
const sequence=++renderSequence;
|
||
if(!isSystemManager()){clearPreviewSurface();syncControls();return;}
|
||
const role=activeRole();
|
||
closePupilWidgetPicker();
|
||
document.body.classList.remove("role-preview-active","role-preview-parent","role-preview-pupil");
|
||
stopPupilView();
|
||
stopParentView();
|
||
if(role==="parent"){
|
||
document.body.classList.add("role-preview-active","role-preview-parent","parent-mode");
|
||
renderParentView([]);
|
||
const inner=parentView.querySelector(".parent-inner");
|
||
if(inner)inner.prepend(previewNotice(T("vwParentPreview")));
|
||
parentView.querySelectorAll("button,input,select,textarea").forEach(control=>{control.disabled=true;});
|
||
}else if(role==="pupil"){
|
||
document.body.classList.add("role-preview-active","role-preview-pupil","pupil-mode");
|
||
const snapshot=serializeBoard();
|
||
await renderPupilWidgets(snapshot.widgets||[],"kijken",true);
|
||
if(sequence!==renderSequence)return;
|
||
const note=previewNotice(T("vwPupilPreview"));
|
||
const add=document.createElement("button");
|
||
add.type="button";add.className="tbtn role-preview-add-widget";
|
||
add.textContent="+ "+T("vwPupilAddWidget");
|
||
add.addEventListener("click",openPupilWidgetPicker);
|
||
note.appendChild(add);
|
||
pupilView.prepend(note);
|
||
}
|
||
syncControls();
|
||
}
|
||
function chooseRole(role){
|
||
if(!isSystemManager()||!VIEW_ROLES.includes(role))return;
|
||
setActiveViewRole(role);
|
||
storeRole(role);
|
||
updateUserUI();
|
||
document.dispatchEvent(new CustomEvent("userchange"));
|
||
}
|
||
|
||
roleSeg.querySelectorAll("button").forEach(button=>{
|
||
button.addEventListener("click",()=>chooseRole(button.dataset.role));
|
||
});
|
||
resetButton.addEventListener("click",()=>chooseRole("super"));
|
||
document.addEventListener("userchange",()=>{
|
||
if(isSystemManager()){
|
||
const saved=storedRole();
|
||
if(activeRole()!==saved)setActiveViewRole(saved);
|
||
}else{
|
||
setActiveViewRole("super");
|
||
}
|
||
syncControls();
|
||
renderPreviewSurface();
|
||
});
|
||
document.addEventListener("langchange",()=>{
|
||
syncControls();
|
||
if(isSystemManager()&&["parent","pupil"].includes(activeRole()))renderPreviewSurface();
|
||
});
|
||
syncControls();
|
||
})();
|