537 lines
19 KiB
JavaScript
537 lines
19 KiB
JavaScript
// 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 defaultBreakInput = document.getElementById('defaultBreakMinutes');
|
|
const defaultBreakVal = defaultBreakInput && defaultBreakInput.value !== '' ? parseInt(defaultBreakInput.value, 10) : 30;
|
|
const default_break_minutes = (!isNaN(defaultBreakVal) && defaultBreakVal >= 0) ? defaultBreakVal : 30;
|
|
|
|
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,
|
|
arbeitstage: document.getElementById('arbeitstage').value,
|
|
urlaubstage: document.getElementById('urlaubstage').value,
|
|
default_break_minutes: default_break_minutes
|
|
};
|
|
|
|
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();
|
|
|
|
// Optionen laden
|
|
loadOptions();
|
|
|
|
// MSSQL-Konfiguration laden
|
|
loadMssqlConfig();
|
|
|
|
// Optionen-Formular
|
|
const optionsForm = document.getElementById('optionsForm');
|
|
if (optionsForm) {
|
|
optionsForm.addEventListener('submit', async function(e) {
|
|
e.preventDefault();
|
|
|
|
const formData = {
|
|
saturday_percentage: document.getElementById('saturdayPercentage').value,
|
|
sunday_percentage: document.getElementById('sundayPercentage').value,
|
|
checkin_root_url: document.getElementById('checkinRootUrl') ? document.getElementById('checkinRootUrl').value : null
|
|
};
|
|
|
|
try {
|
|
const response = await fetch('/admin/options', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(formData)
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.success) {
|
|
alert('Optionen wurden erfolgreich gespeichert!');
|
|
} else {
|
|
alert('Fehler: ' + (result.error || 'Optionen konnten nicht gespeichert werden'));
|
|
}
|
|
} catch (error) {
|
|
console.error('Fehler:', error);
|
|
alert('Fehler beim Speichern der Optionen');
|
|
}
|
|
});
|
|
}
|
|
|
|
// 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');
|
|
}
|
|
});
|
|
}
|
|
|
|
// MSSQL-Konfigurationsformular
|
|
const mssqlConfigForm = document.getElementById('mssqlConfigForm');
|
|
if (mssqlConfigForm) {
|
|
mssqlConfigForm.addEventListener('submit', async function(e) {
|
|
e.preventDefault();
|
|
|
|
const server = document.getElementById('mssqlServer').value;
|
|
const database = document.getElementById('mssqlDatabase').value;
|
|
const username = document.getElementById('mssqlUsername').value;
|
|
const password = document.getElementById('mssqlPassword').value;
|
|
|
|
if (!server || !database || !username) {
|
|
alert('Bitte Server, Datenbankname und Benutzername ausfüllen.');
|
|
return;
|
|
}
|
|
|
|
const formData = { server, database, username, password };
|
|
|
|
try {
|
|
const response = await fetch('/admin/mssql-config', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(formData)
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.success) {
|
|
alert('MSSQL-Konfiguration wurde erfolgreich gespeichert!');
|
|
// Passwort-Feld leeren nach dem Speichern
|
|
document.getElementById('mssqlPassword').value = '';
|
|
} else {
|
|
alert('Fehler: ' + (result.error || 'MSSQL-Konfiguration konnte nicht gespeichert werden'));
|
|
}
|
|
} catch (error) {
|
|
console.error('Fehler:', error);
|
|
alert('Fehler beim Speichern der MSSQL-Konfiguration');
|
|
}
|
|
});
|
|
}
|
|
|
|
// MSSQL Test-Verbindung
|
|
const mssqlTestBtn = document.getElementById('mssqlTestConnectionBtn');
|
|
if (mssqlTestBtn) {
|
|
mssqlTestBtn.addEventListener('click', async function() {
|
|
const statusEl = document.getElementById('mssqlTestStatus');
|
|
mssqlTestBtn.disabled = true;
|
|
if (statusEl) {
|
|
statusEl.textContent = 'Verbindung wird getestet...';
|
|
statusEl.style.color = 'blue';
|
|
}
|
|
|
|
try {
|
|
const response = await fetch('/admin/mssql-test-connection', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (response.ok && result && result.success) {
|
|
if (statusEl) {
|
|
statusEl.textContent = 'Verbindung erfolgreich.';
|
|
statusEl.style.color = 'green';
|
|
}
|
|
} else {
|
|
const msg = (result && result.error) ? result.error : 'Testverbindung fehlgeschlagen.';
|
|
if (statusEl) {
|
|
statusEl.textContent = msg;
|
|
statusEl.style.color = 'red';
|
|
}
|
|
alert(msg);
|
|
}
|
|
} catch (error) {
|
|
console.error('Fehler bei MSSQL-Testverbindung:', error);
|
|
if (statusEl) {
|
|
statusEl.textContent = 'Fehler bei der Testverbindung.';
|
|
statusEl.style.color = 'red';
|
|
}
|
|
alert('Fehler bei der Testverbindung zur MSSQL-Datenbank.');
|
|
} finally {
|
|
mssqlTestBtn.disabled = false;
|
|
}
|
|
});
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// Optionen laden und Formular ausfüllen
|
|
async function loadOptions() {
|
|
try {
|
|
const response = await fetch('/admin/options');
|
|
const result = await response.json();
|
|
|
|
if (result.config) {
|
|
const config = result.config;
|
|
|
|
if (document.getElementById('saturdayPercentage')) {
|
|
document.getElementById('saturdayPercentage').value = config.saturday_percentage || 0;
|
|
}
|
|
if (document.getElementById('sundayPercentage')) {
|
|
document.getElementById('sundayPercentage').value = config.sunday_percentage || 0;
|
|
}
|
|
if (document.getElementById('checkinRootUrl')) {
|
|
document.getElementById('checkinRootUrl').value = config.checkin_root_url || '';
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Fehler beim Laden der Optionen:', error);
|
|
}
|
|
}
|
|
|
|
// 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 || 'sAMAccountName';
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
|
|
// MSSQL-Konfiguration laden und Formular ausfüllen
|
|
async function loadMssqlConfig() {
|
|
try {
|
|
const response = await fetch('/admin/mssql-config');
|
|
const result = await response.json();
|
|
|
|
if (result.config) {
|
|
const config = result.config;
|
|
|
|
if (document.getElementById('mssqlServer')) {
|
|
document.getElementById('mssqlServer').value = config.server || '';
|
|
}
|
|
if (document.getElementById('mssqlDatabase')) {
|
|
document.getElementById('mssqlDatabase').value = config.database || '';
|
|
}
|
|
if (document.getElementById('mssqlUsername')) {
|
|
document.getElementById('mssqlUsername').value = config.username || '';
|
|
}
|
|
// Passwort wird aus Sicherheitsgründen nie vorausgefüllt
|
|
}
|
|
} catch (error) {
|
|
console.error('Fehler beim Laden der MSSQL-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 arbeitstage = row.querySelector('input[data-field="arbeitstage"]').value;
|
|
const urlaubstage = row.querySelector('input[data-field="urlaubstage"]').value;
|
|
const defaultBreakInput = row.querySelector('input[data-field="default_break_minutes"]');
|
|
const default_break_minutes = defaultBreakInput && defaultBreakInput.value !== '' ? parseInt(defaultBreakInput.value, 10) : 30;
|
|
const normalizedDefaultBreak = (!isNaN(default_break_minutes) && default_break_minutes >= 0) ? default_break_minutes : 30;
|
|
|
|
// 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,
|
|
arbeitstage: arbeitstage || 5,
|
|
urlaubstage: urlaubstage || null,
|
|
default_break_minutes: normalizedDefaultBreak,
|
|
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 || '-';
|
|
const defaultBreakDisplay = row.querySelector('span[data-field="default_break_minutes"]');
|
|
if (defaultBreakDisplay) defaultBreakDisplay.textContent = normalizedDefaultBreak;
|
|
|
|
// 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';
|
|
}
|