v0.2.14-beta: beheerpaneel volledig geïntegreerd in Instellingen (één overzicht)
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 18s
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 18s
- Het beheerpaneel opende nog als los venster (adminWrap) boven op Instellingen; nu is het een tabblad ("Account"/"Beheer") binnen hetzelfde Instellingen-scherm - één modal, geen twee
- adminWrap/adminModal-als-los-venster verwijderd; admin.js rendert nu in een contentblok binnen settingsModal, zonder eigen dubbele titel/sluitknop (die van Instellingen zelf dekt dat al)
- Instellingen is breder geworden om ruimte te bieden aan de beheerinhoud (klassen, gebruikers, aanmaakformulieren); het accountgedeelte blijft smal en overzichtelijk via een eigen max-breedte
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
43c7892eb7
commit
baf2a4cb13
4 changed files with 54 additions and 49 deletions
|
|
@ -413,7 +413,11 @@
|
||||||
.gcard .gn{font-weight:800; margin-top:8px; font-size:15px;}
|
.gcard .gn{font-weight:800; margin-top:8px; font-size:15px;}
|
||||||
.gcard .gd{font-size:12.5px; color:var(--muted); margin-top:4px; line-height:1.35;}
|
.gcard .gd{font-size:12.5px; color:var(--muted); margin-top:4px; line-height:1.35;}
|
||||||
/* login + instellingen modals */
|
/* login + instellingen modals */
|
||||||
#loginModal,#settingsModal{width:min(400px,92vw);}
|
#loginModal{width:min(400px,92vw);}
|
||||||
|
/* instellingen is breder dan het inlogscherm: het beheerpaneel (tabblad) heeft
|
||||||
|
de ruimte nodig van wat vroeger een eigen, brede modal was (#adminModal) */
|
||||||
|
#settingsModal{width:min(760px,94vw); max-height:86vh; overflow:auto;}
|
||||||
|
#settingsAccountPanel{max-width:400px;}
|
||||||
#loginModal input,#settingsModal input{
|
#loginModal input,#settingsModal input{
|
||||||
width:100%; border:2px solid #cdd9e8; border-radius:12px; padding:11px 12px;
|
width:100%; border:2px solid #cdd9e8; border-radius:12px; padding:11px 12px;
|
||||||
font:inherit; font-size:16px; outline:none; margin-bottom:10px;
|
font:inherit; font-size:16px; outline:none; margin-bottom:10px;
|
||||||
|
|
@ -428,7 +432,7 @@
|
||||||
.guestnote{font-size:13px; color:var(--muted); margin-top:12px; line-height:1.45;}
|
.guestnote{font-size:13px; color:var(--muted); margin-top:12px; line-height:1.45;}
|
||||||
/* instellingen: neutrale kaarten per sectie (.am-reset, hergebruikt van het
|
/* instellingen: neutrale kaarten per sectie (.am-reset, hergebruikt van het
|
||||||
beheerpaneel) i.p.v. het speelse bord-uiterlijk - dit scherm is voor volwassenen */
|
beheerpaneel) i.p.v. het speelse bord-uiterlijk - dit scherm is voor volwassenen */
|
||||||
#settingsModal .am-h3:first-of-type{margin-top:0;}
|
#settingsAccountPanel .am-h3:first-of-type{margin-top:0;}
|
||||||
#settingsModal .am-reset .lrow{margin:0;}
|
#settingsModal .am-reset .lrow{margin:0;}
|
||||||
#settingsModal .am-reset .guestnote{margin-top:2px;}
|
#settingsModal .am-reset .guestnote{margin-top:2px;}
|
||||||
.st-footer{
|
.st-footer{
|
||||||
|
|
@ -982,8 +986,7 @@
|
||||||
flex:1; min-width:0; border:2px solid #cdd9e8; border-radius:12px;
|
flex:1; min-width:0; border:2px solid #cdd9e8; border-radius:12px;
|
||||||
padding:10px 12px; font:inherit; font-size:15px; outline:none;
|
padding:10px 12px; font:inherit; font-size:15px; outline:none;
|
||||||
}
|
}
|
||||||
/* ---------- beheerpaneel ---------- */
|
/* ---------- beheerpaneel (tabblad "Beheer" binnen Instellingen) ---------- */
|
||||||
#adminModal{width:min(760px,94vw); max-height:86vh; overflow:auto;}
|
|
||||||
.am-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:8px;}
|
.am-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:8px;}
|
||||||
.am-head h2{margin:0; font-size:20px;}
|
.am-head h2{margin:0; font-size:20px;}
|
||||||
.am-h3{margin:14px 0 6px; font-size:14px; color:var(--muted); text-transform:uppercase; letter-spacing:.5px;}
|
.am-h3{margin:14px 0 6px; font-size:14px; color:var(--muted); text-transform:uppercase; letter-spacing:.5px;}
|
||||||
|
|
|
||||||
|
|
@ -103,38 +103,41 @@
|
||||||
<button class="wclose" id="btnSettingsClose">✕</button>
|
<button class="wclose" id="btnSettingsClose">✕</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="am-h3" data-i18n="stAccount"></div>
|
<div class="ed-tabs" id="settingsTabs">
|
||||||
<div class="am-reset">
|
<button type="button" class="active" data-tab="account" data-i18n="stAccount"></button>
|
||||||
<div class="am-name" id="helloName"></div>
|
<button type="button" data-tab="admin" id="btnAdmin" style="display:none;" data-i18n="beheer"></button>
|
||||||
<div class="am-role" id="helloRole"></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="am-h3" data-i18n="stPassword"></div>
|
<div id="settingsAccountPanel">
|
||||||
<div class="am-reset" id="ownPwBlock">
|
<div class="am-reset">
|
||||||
<div id="settingsMsg" class="formMsg"></div>
|
<div class="am-name" id="helloName"></div>
|
||||||
<div class="lrow">
|
<div class="am-role" id="helloRole"></div>
|
||||||
<input type="password" id="ownPw" maxlength="64" autocomplete="new-password">
|
|
||||||
<button class="tbtn ghost pwtoggle" type="button" id="btnOwnPwToggle" data-i18n="pwShow"></button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="lrow">
|
|
||||||
<input type="password" id="ownPw2" maxlength="64" autocomplete="new-password">
|
<div class="am-h3" data-i18n="stPassword"></div>
|
||||||
<button class="tbtn ghost" id="btnOwnPw" data-i18n="pwChange"></button>
|
<div class="am-reset" id="ownPwBlock">
|
||||||
|
<div id="settingsMsg" class="formMsg"></div>
|
||||||
|
<div class="lrow">
|
||||||
|
<input type="password" id="ownPw" maxlength="64" autocomplete="new-password">
|
||||||
|
<button class="tbtn ghost pwtoggle" type="button" id="btnOwnPwToggle" data-i18n="pwShow"></button>
|
||||||
|
</div>
|
||||||
|
<div class="lrow">
|
||||||
|
<input type="password" id="ownPw2" maxlength="64" autocomplete="new-password">
|
||||||
|
<button class="tbtn ghost" id="btnOwnPw" data-i18n="pwChange"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="am-h3" data-i18n="stSession"></div>
|
||||||
|
<div class="am-reset">
|
||||||
|
<div class="lrow">
|
||||||
|
<button class="tbtn ghost" id="btnLogout" data-i18n="logout"></button>
|
||||||
|
</div>
|
||||||
|
<div class="guestnote" data-i18n="storedNote"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="am-h3" id="stAdminLbl" data-i18n="beheer" style="display:none;"></div>
|
<div id="settingsAdminPanel" style="display:none;">
|
||||||
<div class="am-reset" id="adminBlock" style="display:none;">
|
<div id="adminModal"></div>
|
||||||
<div class="lrow">
|
|
||||||
<button class="tbtn ghost" id="btnAdmin">👥 <span data-i18n="openAdmin"></span></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="am-h3" data-i18n="stSession"></div>
|
|
||||||
<div class="am-reset">
|
|
||||||
<div class="lrow">
|
|
||||||
<button class="tbtn ghost" id="btnLogout" data-i18n="logout"></button>
|
|
||||||
</div>
|
|
||||||
<div class="guestnote" data-i18n="storedNote"></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="st-footer">
|
<div class="st-footer">
|
||||||
|
|
@ -143,9 +146,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modalwrap" id="adminWrap">
|
|
||||||
<div class="modal" id="adminModal"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="js/core.js"></script>
|
<script src="js/core.js"></script>
|
||||||
<script src="js/permissions.js"></script>
|
<script src="js/permissions.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
Zichtbaar voor super (alles), admin (eigen school) en teacher (leerlingen). */
|
Zichtbaar voor super (alles), admin (eigen school) en teacher (leerlingen). */
|
||||||
"use strict";
|
"use strict";
|
||||||
(function(){
|
(function(){
|
||||||
const wrap = document.getElementById("adminWrap");
|
/* het beheerpaneel is een tabblad binnen Instellingen (settingsWrap/settingsModal),
|
||||||
|
geen los venster meer - modal is alleen nog de content-container voor render() */
|
||||||
const modal = document.getElementById("adminModal");
|
const modal = document.getElementById("adminModal");
|
||||||
const btn = document.getElementById("btnAdmin");
|
const btn = document.getElementById("btnAdmin");
|
||||||
let SCHOOLS = [], USERS = [], CLASSES = [], selSchool = null;
|
let SCHOOLS = [], USERS = [], CLASSES = [], selSchool = null;
|
||||||
|
|
@ -53,10 +54,9 @@
|
||||||
if(!can("admin.access")) return;
|
if(!can("admin.access")) return;
|
||||||
selSchool = currentUser.role==="super" ? (selSchool ?? "") : currentUser.schoolId;
|
selSchool = currentUser.role==="super" ? (selSchool ?? "") : currentUser.schoolId;
|
||||||
await reload();
|
await reload();
|
||||||
wrap.classList.add("open");
|
switchSettingsTab("admin");
|
||||||
});
|
});
|
||||||
wrap.addEventListener("click", e=>{ if(e.target===wrap) wrap.classList.remove("open"); });
|
document.addEventListener("userchange", ()=>{ if(!currentUser) resetResults = null; });
|
||||||
document.addEventListener("userchange", ()=>{ if(!currentUser){ wrap.classList.remove("open"); resetResults = null; } });
|
|
||||||
|
|
||||||
async function reload(){
|
async function reload(){
|
||||||
try{
|
try{
|
||||||
|
|
@ -266,12 +266,6 @@
|
||||||
|
|
||||||
function render(){
|
function render(){
|
||||||
modal.innerHTML = "";
|
modal.innerHTML = "";
|
||||||
const head = h("div","am-head");
|
|
||||||
head.appendChild(h("h2", null, T("beheer")));
|
|
||||||
const close = h("button","wclose","✕");
|
|
||||||
close.addEventListener("click", ()=>wrap.classList.remove("open"));
|
|
||||||
head.appendChild(close);
|
|
||||||
modal.appendChild(head);
|
|
||||||
|
|
||||||
/* super: schoolkiezer + nieuwe school */
|
/* super: schoolkiezer + nieuwe school */
|
||||||
if(currentUser.role==="super"){
|
if(currentUser.role==="super"){
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ const I18N = {
|
||||||
tmHint:"Sleep aan de rode schijf om de tijd in te stellen.",
|
tmHint:"Sleep aan de rode schijf om de tijd in te stellen.",
|
||||||
login:"Inloggen", loginBtn:"Inloggen", registerBtn:"Account maken", logout:"Uitloggen",
|
login:"Inloggen", loginBtn:"Inloggen", registerBtn:"Account maken", logout:"Uitloggen",
|
||||||
settingsTitle:"Instellingen", tabLogin:"Inloggen", tabLinkCode:"Koppelcode", busy:"Bezig…",
|
settingsTitle:"Instellingen", tabLogin:"Inloggen", tabLinkCode:"Koppelcode", busy:"Bezig…",
|
||||||
stAccount:"Account", stPassword:"Wachtwoord", stSession:"Sessie", openAdmin:"Beheerpaneel",
|
stAccount:"Account", stPassword:"Wachtwoord", stSession:"Sessie",
|
||||||
pwChanged:"Wachtwoord gewijzigd ✓",
|
pwChanged:"Wachtwoord gewijzigd ✓",
|
||||||
namePh:"naam", passPh:"wachtwoord",
|
namePh:"naam", passPh:"wachtwoord",
|
||||||
guestNote:"Zonder inloggen wordt niets bewaard. Log in met je schoolaccount om alles op de server te bewaren.",
|
guestNote:"Zonder inloggen wordt niets bewaard. Log in met je schoolaccount om alles op de server te bewaren.",
|
||||||
|
|
@ -239,7 +239,7 @@ const I18N = {
|
||||||
tmHint:"Drag the red disc to set the time.",
|
tmHint:"Drag the red disc to set the time.",
|
||||||
login:"Log in", loginBtn:"Log in", registerBtn:"Create account", logout:"Log out",
|
login:"Log in", loginBtn:"Log in", registerBtn:"Create account", logout:"Log out",
|
||||||
settingsTitle:"Settings", tabLogin:"Log in", tabLinkCode:"Link code", busy:"Please wait…",
|
settingsTitle:"Settings", tabLogin:"Log in", tabLinkCode:"Link code", busy:"Please wait…",
|
||||||
stAccount:"Account", stPassword:"Password", stSession:"Session", openAdmin:"Admin panel",
|
stAccount:"Account", stPassword:"Password", stSession:"Session",
|
||||||
pwChanged:"Password changed ✓",
|
pwChanged:"Password changed ✓",
|
||||||
namePh:"name", passPh:"password",
|
namePh:"name", passPh:"password",
|
||||||
guestNote:"Without logging in nothing is saved. Log in with your school account to keep everything on the server.",
|
guestNote:"Without logging in nothing is saved. Log in with your school account to keep everything on the server.",
|
||||||
|
|
@ -376,9 +376,10 @@ const roleKey = r => r==="super" ? "roleSuper" : r==="admin" ? "roleAdmin" : r==
|
||||||
function updateUserUI(){
|
function updateUserUI(){
|
||||||
document.getElementById("userLbl").textContent = currentUser ? currentUser.displayName : T("login");
|
document.getElementById("userLbl").textContent = currentUser ? currentUser.displayName : T("login");
|
||||||
document.getElementById("btnUser").classList.toggle("on", !!currentUser);
|
document.getElementById("btnUser").classList.toggle("on", !!currentUser);
|
||||||
|
const adminTabBtn = document.getElementById("btnAdmin");
|
||||||
const showAdmin = can("admin.access");
|
const showAdmin = can("admin.access");
|
||||||
document.getElementById("stAdminLbl").style.display = showAdmin ? "" : "none";
|
adminTabBtn.style.display = showAdmin ? "" : "none";
|
||||||
document.getElementById("adminBlock").style.display = showAdmin ? "flex" : "none";
|
if(!showAdmin && adminTabBtn.classList.contains("active")) switchSettingsTab("account");
|
||||||
if(currentUser){
|
if(currentUser){
|
||||||
document.getElementById("helloName").textContent = currentUser.displayName;
|
document.getElementById("helloName").textContent = currentUser.displayName;
|
||||||
document.getElementById("helloRole").textContent = T(roleKey(currentUser.role));
|
document.getElementById("helloRole").textContent = T(roleKey(currentUser.role));
|
||||||
|
|
@ -394,6 +395,14 @@ function switchLoginTab(tab){
|
||||||
document.querySelectorAll("#loginModal .ed-tabs button").forEach(b=>{
|
document.querySelectorAll("#loginModal .ed-tabs button").forEach(b=>{
|
||||||
b.addEventListener("click", ()=>switchLoginTab(b.dataset.tab));
|
b.addEventListener("click", ()=>switchLoginTab(b.dataset.tab));
|
||||||
});
|
});
|
||||||
|
/* instellingen-tabs: "account" vs "beheer" - alles in één overzicht i.p.v. een los venster */
|
||||||
|
function switchSettingsTab(tab){
|
||||||
|
document.querySelectorAll("#settingsTabs button").forEach(b=>b.classList.toggle("active", b.dataset.tab===tab));
|
||||||
|
document.getElementById("settingsAccountPanel").style.display = tab==="account" ? "block" : "none";
|
||||||
|
document.getElementById("settingsAdminPanel").style.display = tab==="admin" ? "block" : "none";
|
||||||
|
}
|
||||||
|
/* het "beheer"-tabblad heeft zijn eigen klik-handler in admin.js (moet eerst data laden) */
|
||||||
|
document.querySelector('#settingsTabs button[data-tab="account"]').addEventListener("click", ()=>switchSettingsTab("account"));
|
||||||
async function loadSchools(){
|
async function loadSchools(){
|
||||||
const sel = document.getElementById("liSchool");
|
const sel = document.getElementById("liSchool");
|
||||||
try{
|
try{
|
||||||
|
|
@ -404,6 +413,7 @@ async function loadSchools(){
|
||||||
}
|
}
|
||||||
function openSettings(){
|
function openSettings(){
|
||||||
settingsMsg.textContent = ""; settingsMsg.classList.remove("ok");
|
settingsMsg.textContent = ""; settingsMsg.classList.remove("ok");
|
||||||
|
switchSettingsTab("account");
|
||||||
settingsWrap.classList.add("open");
|
settingsWrap.classList.add("open");
|
||||||
}
|
}
|
||||||
document.getElementById("btnUser").addEventListener("click", ()=>{
|
document.getElementById("btnUser").addEventListener("click", ()=>{
|
||||||
|
|
@ -414,8 +424,6 @@ document.getElementById("btnUser").addEventListener("click", ()=>{
|
||||||
loginWrap.classList.add("open");
|
loginWrap.classList.add("open");
|
||||||
});
|
});
|
||||||
document.getElementById("btnSettingsClose").addEventListener("click", ()=>settingsWrap.classList.remove("open"));
|
document.getElementById("btnSettingsClose").addEventListener("click", ()=>settingsWrap.classList.remove("open"));
|
||||||
/* Beheer wordt vanuit Instellingen geopend: dat scherm zelf dicht zodat er geen twee modals over elkaar staan */
|
|
||||||
document.getElementById("btnAdmin").addEventListener("click", ()=>settingsWrap.classList.remove("open"));
|
|
||||||
loginWrap.addEventListener("click", e=>{ if(e.target===loginWrap) loginWrap.classList.remove("open"); });
|
loginWrap.addEventListener("click", e=>{ if(e.target===loginWrap) loginWrap.classList.remove("open"); });
|
||||||
settingsWrap.addEventListener("click", e=>{ if(e.target===settingsWrap) settingsWrap.classList.remove("open"); });
|
settingsWrap.addEventListener("click", e=>{ if(e.target===settingsWrap) settingsWrap.classList.remove("open"); });
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue