v0.3.32-beta: één tabbalk in Instellingen (geen geneste beheer-tabs meer)
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 21s

- De beheer-tabs (Systeem/Klassen/Gebruikers/Toewijzingen/Voortgang) staan
  nu als losse knoppen direct in de instellingen-tabbalk naast Account en
  Weergave, in plaats van een tweede tabbalk binnen het Beheer-tabblad
- admin.js vult #adminTabsSlot en herbouwt bij gebruikers-/taalwissel;
  data wordt geladen bij binnenkomst in het beheer-deel, wisselen tussen
  beheer-tabs onderling hergebruikt de geladen data
- De losse "Beheer"-knop en de geneste .ed-tabs-balk zijn verwijderd;
  de tabbalk loopt om op smalle schermen (flex-wrap)
This commit is contained in:
Ramon 2026-07-15 04:37:15 +02:00
parent d5e0b361bf
commit 54eb8b18cb
5 changed files with 59 additions and 35 deletions

View file

@ -1 +1 @@
0.3.31-beta
0.3.32-beta

View file

@ -702,6 +702,9 @@
.ed-tabs{
display:flex; gap:2px; border-bottom:1px solid var(--line); margin-bottom:14px;
}
/* de instellingen-balk bevat nu ook alle beheer-tabs: laten omlopen op
smalle schermen i.p.v. overlopen */
#settingsTabs{flex-wrap:wrap;}
.ed-tabs button{
border:none; border-radius:0; padding:10px 15px 11px; font:inherit; font-weight:700;
font-size:14px; background:transparent; color:var(--muted); cursor:pointer;

View file

@ -142,7 +142,7 @@
<div class="ed-tabs" id="settingsTabs">
<button type="button" class="active" data-tab="account" data-i18n="stAccount"></button>
<button type="button" data-tab="view" data-i18n="stView"></button>
<button type="button" data-tab="admin" id="btnAdmin" style="display:none;" data-i18n="beheer"></button>
<span id="adminTabsSlot" style="display:none;"></span>
</div>
<div id="settingsAccountPanel">

View file

@ -5,7 +5,6 @@
/* 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 btn = document.getElementById("btnAdmin");
let SCHOOLS = [], USERS = [], CLASSES = [], selSchool = null;
/* huidige klas-toewijzingen (leerling-omgeving), per klas-id - opnieuw
opgehaald bij elke reload() zoals CLASSES/USERS hierboven */
@ -61,13 +60,46 @@
if(copyValue) m.appendChild(copyBtn(copyValue));
};
btn.addEventListener("click", async ()=>{
if(!can("admin.access")) return;
selSchool = currentUser.role==="super" ? (selSchool ?? "") : currentUser.schoolId;
await reload();
switchSettingsTab("admin");
/* de beheer-tabs staan als losse knoppen in de ene instellingen-tabbalk
(#adminTabsSlot in core.js/index.html) - geen geneste tabbalk meer */
const adminTabDefs = ()=>{
const defs = [];
if(currentUser && currentUser.role==="super") defs.push(["scholen", T("amOverarching")]);
defs.push(["klassen", T("amClasses")]);
defs.push(["gebruikers", T("amUsers")]);
defs.push(["toewijzingen", T("amAssignments")]);
defs.push(["voortgang", T("amProgress")]);
return defs;
};
function buildAdminTabs(){
const slot = document.getElementById("adminTabsSlot");
slot.innerHTML = "";
if(!currentUser || !can("admin.access")) return;
adminTabDefs().forEach(([t, label])=>{
const b = h("button", null, label);
b.type = "button";
b.dataset.tab = "admin";
b.dataset.admintab = t;
b.addEventListener("click", async ()=>{
adminTab = t;
/* data (opnieuw) laden bij binnenkomst in het beheer-deel; wisselen
tussen beheer-tabs onderling hergebruikt de geladen data */
const adminVisible = document.getElementById("settingsAdminPanel").style.display !== "none";
if(!adminVisible){
selSchool = currentUser.role==="super" ? (selSchool ?? "") : currentUser.schoolId;
await reload();
}
switchSettingsTab("admin");
switchAdminTab(t);
});
slot.appendChild(b);
});
}
document.addEventListener("userchange", ()=>{
if(!currentUser) resetResults = null;
buildAdminTabs();
});
document.addEventListener("userchange", ()=>{ if(!currentUser) resetResults = null; });
document.addEventListener("langchange", buildAdminTabs);
async function reload(){
try{
@ -672,7 +704,7 @@
function switchAdminTab(tab){
adminTab = tab;
modal.querySelectorAll(".ed-tabs button").forEach(b=>b.classList.toggle("active", b.dataset.tab===tab));
document.querySelectorAll("#adminTabsSlot button").forEach(b=>b.classList.toggle("active", b.dataset.admintab===tab));
modal.querySelectorAll(".am-tabpanel").forEach(p=>{ p.style.display = p.dataset.panel===tab ? "block" : "none"; });
}
@ -682,24 +714,9 @@
const rp = resetPanel();
if(rp) modal.appendChild(rp);
const tabDefs = [];
if(currentUser.role==="super") tabDefs.push(["scholen", T("amOverarching")]);
tabDefs.push(["klassen", T("amClasses")]);
tabDefs.push(["gebruikers", T("amUsers")]);
tabDefs.push(["toewijzingen", T("amAssignments")]);
tabDefs.push(["voortgang", T("amProgress")]);
const tabDefs = adminTabDefs();
if(!tabDefs.some(([t])=>t===adminTab)) adminTab = tabDefs[0][0];
const tabsBar = h("div","ed-tabs");
tabDefs.forEach(([t, label])=>{
const b = h("button", null, label);
b.type = "button";
b.dataset.tab = t;
b.addEventListener("click", ()=>switchAdminTab(t));
tabsBar.appendChild(b);
});
modal.appendChild(tabsBar);
const panels = { scholen: renderScholenPanel, klassen: renderKlassenPanel, gebruikers: renderGebruikersPanel, toewijzingen: renderToewijzingenPanel, voortgang: renderVoortgangPanel };
tabDefs.forEach(([t])=>{
const panel = h("div","am-tabpanel");

View file

@ -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.3.31-beta";
const VERSION = "0.3.32-beta";
(function(){
const tag = document.getElementById("verTag");
tag.textContent = "v"+VERSION;
@ -175,7 +175,7 @@ const I18N = {
linkBtn:"Account activeren", pwChange:"Wijzig", pwNewPh:"nieuw wachtwoord (min. 8, met cijfer)",
pwConfirmPh:"herhaal wachtwoord", pwShow:"👁 Toon", pwHide:"🙈 Verberg",
errPwMatch:"Wachtwoorden komen niet overeen.",
codePh:"koppelcode", beheer:"Beheer",
codePh:"koppelcode",
roleSuper:"Systeemmanager", roleAdmin:"Schoolbeheerder",
roleTeacher:"Groepsleiding", rolePupil:"Leerling",
pupilEmpty:"Je leerkracht heeft nog niets voor je klaargezet.",
@ -359,7 +359,7 @@ const I18N = {
linkBtn:"Activate account", pwChange:"Change", pwNewPh:"new password (min. 8, incl. number)",
pwConfirmPh:"repeat password", pwShow:"👁 Show", pwHide:"🙈 Hide",
errPwMatch:"Passwords don't match.",
codePh:"link code", beheer:"Management",
codePh:"link code",
roleSuper:"System manager", roleAdmin:"School administrator",
roleTeacher:"Group leader", rolePupil:"Pupil",
pupilEmpty:"Your teacher hasn't set up anything for you yet.",
@ -606,10 +606,12 @@ 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);
const adminTabBtn = document.getElementById("btnAdmin");
/* de beheer-tabs (Systeem/Klassen/Gebruikers/...) staan als losse knoppen
in de ene tabbalk; admin.js vult de slot, hier alleen zichtbaarheid */
const adminSlot = document.getElementById("adminTabsSlot");
const showAdmin = can("admin.access");
adminTabBtn.style.display = showAdmin ? "" : "none";
if(!showAdmin && adminTabBtn.classList.contains("active")) switchSettingsTab("account");
adminSlot.style.display = showAdmin ? "contents" : "none";
if(!showAdmin && adminSlot.querySelector("button.active")) switchSettingsTab("account");
if(currentUser){
document.getElementById("helloName").textContent = currentUser.displayName;
const roles = [currentUser.role, ...(currentUser.extraRoles||[])];
@ -626,14 +628,16 @@ function switchLoginTab(tab){
document.querySelectorAll("#loginModal .ed-tabs button").forEach(b=>{
b.addEventListener("click", ()=>switchLoginTab(b.dataset.tab));
});
/* instellingen-tabs: "account" / "weergave" / "beheer" - alles in één overzicht */
/* instellingen-tabs: één balk met account / weergave / de beheer-tabs
(die laatste worden door admin.js in #adminTabsSlot gezet en zelf
actief gemarkeerd via switchAdminTab) */
function switchSettingsTab(tab){
document.querySelectorAll("#settingsTabs button").forEach(b=>b.classList.toggle("active", b.dataset.tab===tab));
document.querySelectorAll("#settingsTabs button").forEach(b=>b.classList.toggle("active", b.dataset.tab===tab && !b.dataset.admintab));
document.getElementById("settingsAccountPanel").style.display = tab==="account" ? "block" : "none";
document.getElementById("settingsViewPanel").style.display = tab==="view" ? "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) */
/* de beheer-tabs hebben hun eigen klik-handlers in admin.js (moeten eerst data laden) */
document.querySelector('#settingsTabs button[data-tab="account"]').addEventListener("click", ()=>switchSettingsTab("account"));
document.querySelector('#settingsTabs button[data-tab="view"]').addEventListener("click", ()=>switchSettingsTab("view"));
async function loadSchools(){