FirstCommit
This commit is contained in:
1002
public/css/style.css
Normal file
1002
public/css/style.css
Normal file
File diff suppressed because it is too large
Load Diff
342
public/js/admin.js
Normal file
342
public/js/admin.js
Normal file
@@ -0,0 +1,342 @@
|
||||
// Admin JavaScript
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Benutzer-Formular
|
||||
const form = document.getElementById('addUserForm');
|
||||
|
||||
form.addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Rollen aus Checkboxen sammeln
|
||||
const roleCheckboxes = document.querySelectorAll('input[name="roles"]:checked');
|
||||
const roles = Array.from(roleCheckboxes).map(cb => cb.value);
|
||||
|
||||
// Validierung: Mindestens eine Rolle muss ausgewählt sein
|
||||
if (roles.length === 0) {
|
||||
alert('Bitte wählen Sie mindestens eine Rolle aus.');
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = {
|
||||
username: document.getElementById('username').value,
|
||||
password: document.getElementById('password').value,
|
||||
firstname: document.getElementById('firstname').value,
|
||||
lastname: document.getElementById('lastname').value,
|
||||
roles: roles,
|
||||
personalnummer: document.getElementById('personalnummer').value,
|
||||
wochenstunden: document.getElementById('wochenstunden').value,
|
||||
urlaubstage: document.getElementById('urlaubstage').value
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch('/admin/users', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(formData)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
alert('Benutzer wurde erfolgreich angelegt!');
|
||||
location.reload();
|
||||
} else {
|
||||
alert('Fehler: ' + (result.error || 'Benutzer konnte nicht angelegt werden'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler:', error);
|
||||
alert('Fehler beim Anlegen des Benutzers');
|
||||
}
|
||||
});
|
||||
|
||||
// LDAP-Konfiguration laden
|
||||
loadLDAPConfig();
|
||||
|
||||
// LDAP-Konfigurationsformular
|
||||
const ldapConfigForm = document.getElementById('ldapConfigForm');
|
||||
if (ldapConfigForm) {
|
||||
ldapConfigForm.addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const enabled = document.getElementById('ldapEnabled').checked;
|
||||
const url = document.getElementById('ldapUrl').value;
|
||||
const baseDn = document.getElementById('ldapBaseDn').value;
|
||||
|
||||
// Validierung: URL und Base DN sind erforderlich wenn aktiviert
|
||||
if (enabled && (!url || !baseDn)) {
|
||||
alert('Bitte füllen Sie URL und Base DN aus, wenn LDAP aktiviert ist.');
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = {
|
||||
enabled: enabled,
|
||||
url: url,
|
||||
bind_dn: document.getElementById('ldapBindDn').value,
|
||||
bind_password: document.getElementById('ldapBindPassword').value,
|
||||
base_dn: baseDn,
|
||||
user_search_filter: document.getElementById('ldapSearchFilter').value,
|
||||
username_attribute: document.getElementById('ldapUsernameAttr').value,
|
||||
firstname_attribute: document.getElementById('ldapFirstnameAttr').value,
|
||||
lastname_attribute: document.getElementById('ldapLastnameAttr').value,
|
||||
sync_interval: parseInt(document.getElementById('ldapSyncInterval').value) || 0
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch('/admin/ldap/config', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(formData)
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
alert('LDAP-Konfiguration wurde erfolgreich gespeichert!');
|
||||
location.reload();
|
||||
} else {
|
||||
alert('Fehler: ' + (result.error || 'Konfiguration konnte nicht gespeichert werden'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler:', error);
|
||||
alert('Fehler beim Speichern der Konfiguration');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Sync-Button
|
||||
const syncNowBtn = document.getElementById('syncNowBtn');
|
||||
if (syncNowBtn) {
|
||||
syncNowBtn.addEventListener('click', async function() {
|
||||
if (!confirm('Möchten Sie die LDAP-Synchronisation jetzt starten?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const statusEl = document.getElementById('syncStatus');
|
||||
syncNowBtn.disabled = true;
|
||||
statusEl.textContent = 'Synchronisation läuft...';
|
||||
statusEl.style.color = 'blue';
|
||||
|
||||
try {
|
||||
const response = await fetch('/admin/ldap/sync', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
statusEl.textContent = `Erfolgreich: ${result.synced} Benutzer synchronisiert`;
|
||||
statusEl.style.color = 'green';
|
||||
|
||||
if (result.errors && result.errors.length > 0) {
|
||||
alert('Synchronisation abgeschlossen mit Warnungen:\n' + result.errors.join('\n'));
|
||||
} else {
|
||||
alert(`Synchronisation erfolgreich abgeschlossen: ${result.synced} Benutzer synchronisiert`);
|
||||
}
|
||||
|
||||
// Seite neu laden nach kurzer Verzögerung
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
}, 2000);
|
||||
} else {
|
||||
statusEl.textContent = 'Fehler: ' + (result.error || 'Synchronisation fehlgeschlagen');
|
||||
statusEl.style.color = 'red';
|
||||
alert('Fehler: ' + (result.error || 'Synchronisation fehlgeschlagen'));
|
||||
syncNowBtn.disabled = false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler:', error);
|
||||
statusEl.textContent = 'Fehler bei der Synchronisation';
|
||||
statusEl.style.color = 'red';
|
||||
alert('Fehler bei der Synchronisation');
|
||||
syncNowBtn.disabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// LDAP-Konfiguration laden und Formular ausfüllen
|
||||
async function loadLDAPConfig() {
|
||||
try {
|
||||
const response = await fetch('/admin/ldap/config');
|
||||
const result = await response.json();
|
||||
|
||||
if (result.config) {
|
||||
const config = result.config;
|
||||
|
||||
if (document.getElementById('ldapEnabled')) {
|
||||
document.getElementById('ldapEnabled').checked = config.enabled === 1;
|
||||
}
|
||||
if (document.getElementById('ldapUrl')) {
|
||||
document.getElementById('ldapUrl').value = config.url || '';
|
||||
}
|
||||
if (document.getElementById('ldapBaseDn')) {
|
||||
document.getElementById('ldapBaseDn').value = config.base_dn || '';
|
||||
}
|
||||
if (document.getElementById('ldapBindDn')) {
|
||||
document.getElementById('ldapBindDn').value = config.bind_dn || '';
|
||||
}
|
||||
if (document.getElementById('ldapSearchFilter')) {
|
||||
document.getElementById('ldapSearchFilter').value = config.user_search_filter || '(objectClass=person)';
|
||||
}
|
||||
if (document.getElementById('ldapUsernameAttr')) {
|
||||
document.getElementById('ldapUsernameAttr').value = config.username_attribute || 'cn';
|
||||
}
|
||||
if (document.getElementById('ldapFirstnameAttr')) {
|
||||
document.getElementById('ldapFirstnameAttr').value = config.firstname_attribute || 'givenName';
|
||||
}
|
||||
if (document.getElementById('ldapLastnameAttr')) {
|
||||
document.getElementById('ldapLastnameAttr').value = config.lastname_attribute || 'sn';
|
||||
}
|
||||
if (document.getElementById('ldapSyncInterval')) {
|
||||
document.getElementById('ldapSyncInterval').value = config.sync_interval || 0;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der LDAP-Konfiguration:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteUser(userId, username) {
|
||||
const confirmed = confirm(`Möchten Sie den Benutzer "${username}" wirklich löschen?`);
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
try {
|
||||
const response = await fetch(`/admin/users/${userId}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
alert('Benutzer wurde erfolgreich gelöscht!');
|
||||
location.reload();
|
||||
} else {
|
||||
alert('Fehler: ' + (result.error || 'Benutzer konnte nicht gelöscht werden'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler:', error);
|
||||
alert('Fehler beim Löschen des Benutzers');
|
||||
}
|
||||
}
|
||||
|
||||
// User bearbeiten
|
||||
function editUser(userId) {
|
||||
const row = document.querySelector(`tr[data-user-id="${userId}"]`);
|
||||
if (!row) return;
|
||||
|
||||
// Alle Display-Felder ausblenden und Edit-Felder einblenden
|
||||
row.querySelectorAll('.user-field-display').forEach(display => {
|
||||
display.style.display = 'none';
|
||||
});
|
||||
row.querySelectorAll('.user-field-edit').forEach(edit => {
|
||||
edit.style.display = 'inline-block';
|
||||
});
|
||||
|
||||
// Buttons umschalten
|
||||
row.querySelector('.edit-user-btn').style.display = 'none';
|
||||
row.querySelector('.save-user-btn').style.display = 'inline-block';
|
||||
row.querySelector('.cancel-user-btn').style.display = 'inline-block';
|
||||
}
|
||||
|
||||
// User speichern
|
||||
async function saveUser(userId) {
|
||||
const row = document.querySelector(`tr[data-user-id="${userId}"]`);
|
||||
if (!row) return;
|
||||
|
||||
const personalnummer = row.querySelector('input[data-field="personalnummer"]').value;
|
||||
const wochenstunden = row.querySelector('input[data-field="wochenstunden"]').value;
|
||||
const urlaubstage = row.querySelector('input[data-field="urlaubstage"]').value;
|
||||
|
||||
// Rollen aus Checkboxen sammeln
|
||||
const roleCheckboxes = row.querySelectorAll('.role-checkbox:checked');
|
||||
const roles = Array.from(roleCheckboxes).map(cb => cb.value);
|
||||
|
||||
// Validierung: Mindestens eine Rolle erforderlich
|
||||
if (roles.length === 0) {
|
||||
alert('Mindestens eine Rolle muss ausgewählt sein.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/admin/users/${userId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
personalnummer: personalnummer || null,
|
||||
wochenstunden: wochenstunden || null,
|
||||
urlaubstage: urlaubstage || null,
|
||||
roles: roles
|
||||
})
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
// Werte in Display-Felder übernehmen
|
||||
row.querySelector('span[data-field="personalnummer"]').textContent = personalnummer || '-';
|
||||
row.querySelector('span[data-field="wochenstunden"]').textContent = wochenstunden || '-';
|
||||
row.querySelector('span[data-field="urlaubstage"]').textContent = urlaubstage || '-';
|
||||
|
||||
// Rollen-Display aktualisieren
|
||||
const rolesDisplay = row.querySelector('div[data-field="roles"]');
|
||||
if (rolesDisplay) {
|
||||
const roleLabels = { 'mitarbeiter': 'Mitarbeiter', 'verwaltung': 'Verwaltung', 'admin': 'Admin' };
|
||||
rolesDisplay.innerHTML = roles.map(role =>
|
||||
`<span class="role-badge role-${role}" style="margin-right: 5px;">${roleLabels[role] || role}</span>`
|
||||
).join('');
|
||||
}
|
||||
|
||||
// Bearbeitung beenden
|
||||
cancelEditUser(userId);
|
||||
alert('Benutzerdaten wurden erfolgreich gespeichert!');
|
||||
// Seite neu laden um sicherzustellen dass alles korrekt ist
|
||||
location.reload();
|
||||
} else {
|
||||
alert('Fehler: ' + (result.error || 'Daten konnten nicht gespeichert werden'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler:', error);
|
||||
alert('Fehler beim Speichern der Benutzerdaten');
|
||||
}
|
||||
}
|
||||
|
||||
// Bearbeitung abbrechen
|
||||
function cancelEditUser(userId) {
|
||||
const row = document.querySelector(`tr[data-user-id="${userId}"]`);
|
||||
if (!row) return;
|
||||
|
||||
// Alle Edit-Felder ausblenden und Display-Felder einblenden
|
||||
row.querySelectorAll('.user-field-edit').forEach(edit => {
|
||||
edit.style.display = 'none';
|
||||
// Wert zurücksetzen (nur für Input-Felder, nicht für Rollen)
|
||||
const field = edit.dataset.field;
|
||||
if (field !== 'roles') {
|
||||
const display = row.querySelector(`span[data-field="${field}"]`);
|
||||
if (display && edit.tagName === 'INPUT') {
|
||||
edit.value = display.textContent === '-' ? '' : display.textContent;
|
||||
}
|
||||
}
|
||||
});
|
||||
row.querySelectorAll('.user-field-display').forEach(display => {
|
||||
if (display.tagName === 'DIV' || display.tagName === 'SPAN') {
|
||||
display.style.display = 'block';
|
||||
} else {
|
||||
display.style.display = 'inline';
|
||||
}
|
||||
});
|
||||
|
||||
// Buttons umschalten
|
||||
row.querySelector('.edit-user-btn').style.display = 'inline-block';
|
||||
row.querySelector('.save-user-btn').style.display = 'none';
|
||||
row.querySelector('.cancel-user-btn').style.display = 'none';
|
||||
}
|
||||
1107
public/js/dashboard.js
Normal file
1107
public/js/dashboard.js
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user