Termin aus Mail, Rollen & Rechte, Abwesenheiten, Glas-Darstellung und Pi-Betrieb
- Termin aus Mail: Mailtext oder .eml per Drag & Drop/Strg+V auf Terminplan oder Aufgaben, KI schlägt Aufgaben vor, Prüfung im Aufgaben-Panel; neues Notizfeld je Aufgabe (plan_todos.notiz) - Terminplan: Meilensteine ohne Aufgabenbezug je in eigener Zeile, "+ Neu"-Menü klappt neben schmaler Seitenleiste nach rechts, Leistungsphasen - Rollen & Rechte, Abwesenheiten-Seite, Benachrichtigungen, Rundgang - Glas-Darstellung, Logo als Favicon - Pi-Betrieb: PDF-Arbeit im Kindprozess, Wächter, Einrichtungs- und Prüfskript inkl. WLAN-Wächter Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f4fb3c550b
commit
b7e0bd0d92
56 files changed
+12265
-2974
No files matched your search
@@ -73,13 +73,44 @@
|
||||
return Array.from(document.querySelectorAll('#' + containerId + ' input[type="checkbox"]:checked')).map(cb => cb.value);
|
||||
}
|
||||
|
||||
// systemRollen: die Rollen aus „Rollen & Rechte“ (GET /rollen) für die
|
||||
// Auswahl „Rolle“ und die Anzeige in der Tabelle.
|
||||
let systemRollen = [];
|
||||
function ladeSystemRollen(){
|
||||
fetch(baseUrl() + '/rollen')
|
||||
.then(r => r.json())
|
||||
.then(j => {
|
||||
if(!j || !j.ok) return;
|
||||
systemRollen = j.rollen || [];
|
||||
['newUserRole', 'editUserRole'].forEach(id => {
|
||||
const sel = document.getElementById(id);
|
||||
if(!sel) return;
|
||||
const wert = sel.value;
|
||||
sel.innerHTML = systemRollen.map(r => `<option value="${esc(r.key)}">${esc(r.name)}${nurWandtafelRolle(r.key) ? ' (nur Wandtafel)' : ''}</option>`).join('');
|
||||
if(wert && systemRollen.some(r => r.key === wert)) sel.value = wert;
|
||||
});
|
||||
loadAndRenderUsers();
|
||||
})
|
||||
.catch(err => console.error('Rollen laden fehlgeschlagen:', err));
|
||||
}
|
||||
// nurWandtafelRolle: Rolle ohne „Anwendung nutzen“ — sieht nur die
|
||||
// Wandtafel und trägt keine Fachrolle (früher das Kiosk-Konto).
|
||||
function nurWandtafelRolle(key){
|
||||
const r = systemRollen.find(x => x.key === key);
|
||||
return !!r && !r.fest && !(r.rechte || []).includes('app');
|
||||
}
|
||||
function rollenName(key){
|
||||
const r = systemRollen.find(x => x.key === key);
|
||||
return r ? r.name : systemRolleText(key);
|
||||
}
|
||||
|
||||
// onUserRoleChange: wird beim Wechsel der Systemrolle in einem der beiden
|
||||
// Formulare aufgerufen (which = 'new'|'edit'). Ein Kiosk-Konto kann keine
|
||||
// Fachrolle haben (server.js weist das sonst mit 400 zurück) — die
|
||||
// Checkboxen werden deshalb schon hier abgehakt entfernt und gesperrt,
|
||||
// statt den Fehler erst nach dem Absenden zu zeigen.
|
||||
window.onUserRoleChange = function(which){
|
||||
const istKiosk = document.getElementById(which + 'UserRole').value === 'kiosk';
|
||||
const istKiosk = nurWandtafelRolle(document.getElementById(which + 'UserRole').value);
|
||||
const hint = document.getElementById(which + 'UserRoleHint');
|
||||
if(hint) hint.style.display = istKiosk ? '' : 'none';
|
||||
document.querySelectorAll('#' + which + 'UserRoleCheckboxes input[type="checkbox"]').forEach(cb => {
|
||||
@@ -100,6 +131,7 @@
|
||||
// erreichbar (showTab() leitet sie um) und die Endpunkte sind serverseitig
|
||||
// abgesichert. Keine Parameter, keine Rueckgabe.
|
||||
window.renderAdminUsers = function(){
|
||||
ladeSystemRollen();
|
||||
if(!formulareVorbereitet){
|
||||
renderDepartmentOptions('newUserDepartment');
|
||||
renderDepartmentOptions('editUserDepartment');
|
||||
@@ -151,7 +183,7 @@
|
||||
<td>${esc(u.username)}</td>
|
||||
<td>${esc(u.displayName)}</td>
|
||||
<td>${esc(u.email || '')}</td>
|
||||
<td>${esc(systemRolleText(u.role))}</td>
|
||||
<td>${esc(rollenName(u.role))}</td>
|
||||
<td>${deptLabel}</td>
|
||||
<td>${esc(u.initials || '')}</td>
|
||||
<td>${u.capacityHours ? esc(fmtCapacity(u.capacityHours)) : '<span class="hint" style="margin:0">voll</span>'}</td>
|
||||
@@ -202,10 +234,14 @@
|
||||
document.getElementById('newUserFirstName').value = '';
|
||||
document.getElementById('newUserLastName').value = '';
|
||||
document.getElementById('newUserEmail').value = '';
|
||||
document.getElementById('newUserRole').value = 'member';
|
||||
document.getElementById('newUserRole').value = systemRollen.some(r => r.key === 'member') ? 'member' : ((systemRollen.find(r => !r.fest) || {}).key || '');
|
||||
onUserRoleChange('new');
|
||||
document.getElementById('newUserDepartment').value = DEFAULT_DEPARTMENT;
|
||||
document.getElementById('newUserInitials').value = '';
|
||||
document.getElementById('newUserPersonId').value = '';
|
||||
// Sonst übernahm das nächste Konto unbemerkt die Wochenstunden des
|
||||
// zuvor abgebrochenen Dialogs (Teilzeit ohne Absicht).
|
||||
document.getElementById('newUserCapacity').value = '';
|
||||
document.querySelectorAll('#newUserRoleCheckboxes input[type="checkbox"]').forEach(cb => { cb.checked = false; });
|
||||
document.getElementById('newUserPassword').value = '';
|
||||
document.getElementById('newUserPassword').style.display = 'none';
|
||||
@@ -312,7 +348,7 @@
|
||||
// im PDF-Export, ohne dass es dafür irgendeinen Hinweis gäbe. Für ein
|
||||
// Kiosk-Konto gilt das nicht — es soll gerade NICHT in Boards/Auslastung
|
||||
// auftauchen, server.js weist eine gesetzte Fachrolle dort sogar zurück.
|
||||
if(role !== 'kiosk' && (!roles || roles.length === 0)){
|
||||
if(!nurWandtafelRolle(role) && (!roles || roles.length === 0)){
|
||||
errEl.textContent = 'Bitte mindestens eine Rolle wählen (Planung, Projektleitung oder Bauüberwachung) — sonst erscheint der Benutzer in keinem Projektboard.';
|
||||
return;
|
||||
}
|
||||
@@ -341,6 +377,10 @@
|
||||
}
|
||||
closeNewUserModal();
|
||||
loadAndRenderUsers();
|
||||
// Der Server hat das Konto in den Teilnehmerkreis der aktuellen
|
||||
// Sitzung eingetragen — neu laden, sonst fehlt die Person hier bis
|
||||
// zum nächsten Seitenaufruf in Projekten und im Assistenten.
|
||||
if(res.data.sitzungGeaendert && typeof load === 'function') load(true);
|
||||
if(res.data.generatedPassword){
|
||||
showGeneratedPassword(username, res.data.generatedPassword);
|
||||
}
|
||||
@@ -415,6 +455,10 @@
|
||||
}
|
||||
closeEditUserModal();
|
||||
loadAndRenderUsers();
|
||||
// Der Server hat das Konto in den Teilnehmerkreis der aktuellen
|
||||
// Sitzung eingetragen — neu laden, sonst fehlt die Person hier bis
|
||||
// zum nächsten Seitenaufruf in Projekten und im Assistenten.
|
||||
if(res.data.sitzungGeaendert && typeof load === 'function') load(true);
|
||||
}).catch(err => { errEl.textContent = 'Verbindung zum Server fehlgeschlagen: ' + err.message; });
|
||||
};
|
||||
|
||||
@@ -521,6 +565,10 @@
|
||||
return;
|
||||
}
|
||||
loadAndRenderUsers();
|
||||
// Der Server hat das Konto in den Teilnehmerkreis der aktuellen
|
||||
// Sitzung eingetragen — neu laden, sonst fehlt die Person hier bis
|
||||
// zum nächsten Seitenaufruf in Projekten und im Assistenten.
|
||||
if(res.data.sitzungGeaendert && typeof load === 'function') load(true);
|
||||
}).catch(err => alert('Verbindung zum Server fehlgeschlagen: ' + err.message));
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user