OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

admin.js

10 KB
/**
 * IT-Dokumentation - Admin JavaScript
 * Admin-Bereich spezifische Funktionen
 */

'use strict';

window.OpenNIT = window.OpenNIT || {};
OpenNIT.Admin = OpenNIT.Admin || {};

/**
 * Admin-Initialisierung
 */
document.addEventListener('DOMContentLoaded', function() {
    OpenNIT.Admin.init();
});

/**
 * Hauptinitialisierung
 */
OpenNIT.Admin.init = function() {
    this.initDataTables();
    this.initBulkActions();
    this.initCharts();
    this.initAuditFilters();
};

/**
 * Daten-Tabellen erweitern
 */
OpenNIT.Admin.initDataTables = function() {
    // Sortierbare Spalten
    document.querySelectorAll('.data-table .sort-link').forEach(function(link) {
        link.addEventListener('click', function(e) {
            // Lade-Indikator
            this.style.opacity = '0.5';
        });
    });

    // Zeilen-Aktionen
    document.querySelectorAll('.data-table tbody tr').forEach(function(row) {
        // Doppelklick zum Bearbeiten
        row.addEventListener('dblclick', function() {
            const editLink = this.querySelector('a[title="Bearbeiten"]');
            if (editLink) {
                window.location.href = editLink.href;
            }
        });
    });
};

/**
 * Massenaktionen
 */
OpenNIT.Admin.initBulkActions = function() {
    const selectAll = document.querySelector('.bulk-select-all');
    if (!selectAll) return;

    const checkboxes = document.querySelectorAll('.bulk-select');
    const bulkActions = document.querySelector('.bulk-actions');

    // Alle auswählen
    selectAll.addEventListener('change', function() {
        checkboxes.forEach(function(cb) {
            cb.checked = selectAll.checked;
        });
        OpenNIT.Admin.updateBulkActions(bulkActions, checkboxes);
    });

    // Einzelne Checkboxen
    checkboxes.forEach(function(cb) {
        cb.addEventListener('change', function() {
            OpenNIT.Admin.updateBulkActions(bulkActions, checkboxes);

            // "Alle auswählen" Status aktualisieren
            const checkedCount = document.querySelectorAll('.bulk-select:checked').length;
            selectAll.checked = checkedCount === checkboxes.length;
            selectAll.indeterminate = checkedCount > 0 && checkedCount < checkboxes.length;
        });
    });
};

/**
 * Massenaktionen-UI aktualisieren
 */
OpenNIT.Admin.updateBulkActions = function(container, checkboxes) {
    if (!container) return;

    const checkedCount = document.querySelectorAll('.bulk-select:checked').length;

    if (checkedCount > 0) {
        container.style.display = 'flex';
        container.querySelector('.selected-count').textContent = checkedCount + ' ' + window.onitText('ausgewählt');
    } else {
        container.style.display = 'none';
    }
};

/**
 * Charts initialisieren (wenn vorhanden)
 */
OpenNIT.Admin.initCharts = function() {
    // Einfaches Balkendiagramm für Audit-Statistiken
    document.querySelectorAll('[data-chart="bar"]').forEach(function(container) {
        const data = JSON.parse(container.dataset.values || '[]');
        OpenNIT.Admin.renderBarChart(container, data);
    });
};

/**
 * Einfaches Balkendiagramm rendern
 */
OpenNIT.Admin.renderBarChart = function(container, data) {
    if (!data.length) return;

    const maxValue = Math.max(...data.map(function(d) { return d.value; }));
    let html = '<div class="simple-bar-chart">';

    data.forEach(function(item) {
        const percentage = maxValue > 0 ? (item.value / maxValue) * 100 : 0;
        html += '<div class="bar-item">';
        html += '<span class="bar-label">' + OpenNIT.escapeHtml(item.label) + '</span>';
        html += '<div class="bar-track"><div class="bar-fill" style="width: ' + percentage + '%"></div></div>';
        html += '<span class="bar-value">' + item.value + '</span>';
        html += '</div>';
    });

    html += '</div>';
    container.innerHTML = html;
};

/**
 * Audit-Filter
 */
OpenNIT.Admin.initAuditFilters = function() {
    const filterForm = document.querySelector('.audit-page .filter-form');
    if (!filterForm) return;

    // Auto-Submit bei Select-Änderung
    filterForm.querySelectorAll('select').forEach(function(select) {
        select.addEventListener('change', function() {
            // Debounce für schnelle Änderungen
            clearTimeout(this._submitTimeout);
            this._submitTimeout = setTimeout(function() {
                filterForm.submit();
            }, 300);
        });
    });

    // Datum-Validierung
    const dateFrom = filterForm.querySelector('input[name="date_from"]');
    const dateTo = filterForm.querySelector('input[name="date_to"]');

    if (dateFrom && dateTo) {
        dateFrom.addEventListener('change', function() {
            dateTo.min = this.value;
        });
        dateTo.addEventListener('change', function() {
            dateFrom.max = this.value;
        });
    }
};

/**
 * Benutzer deaktivieren
 */
OpenNIT.Admin.deactivateUser = function(userId, userName) {
    if (!confirm('Benutzer "' + userName + '" wirklich deaktivieren?\n\nDer Benutzer kann sich danach nicht mehr anmelden.')) {
        return;
    }

    OpenNIT.fetch('/admin/users/' + userId + '/deactivate', {
        method: 'POST'
    })
    .then(function(response) {
        return response.json();
    })
    .then(function(data) {
        if (data.success) {
            OpenNIT.notify('Benutzer deaktiviert', 'success');
            window.location.reload();
        } else {
            OpenNIT.notify(data.error || 'Fehler beim Deaktivieren', 'error');
        }
    })
    .catch(function() {
        OpenNIT.notify('Fehler beim Deaktivieren', 'error');
    });
};

/**
 * Benutzer aktivieren
 */
OpenNIT.Admin.activateUser = function(userId, userName) {
    OpenNIT.fetch('/admin/users/' + userId + '/activate', {
        method: 'POST'
    })
    .then(function(response) {
        return response.json();
    })
    .then(function(data) {
        if (data.success) {
            OpenNIT.notify('Benutzer aktiviert', 'success');
            window.location.reload();
        } else {
            OpenNIT.notify(data.error || 'Fehler beim Aktivieren', 'error');
        }
    })
    .catch(function() {
        OpenNIT.notify('Fehler beim Aktivieren', 'error');
    });
};

/**
 * Rolle löschen
 */
OpenNIT.Admin.deleteRole = function(roleId, roleName) {
    if (!confirm(window.onitText('Rolle „{name}“ wirklich löschen?').replace('{name}', roleName)
        + '\n\n' + window.onitText('Diese Aktion kann nicht rückgängig gemacht werden.'))) {
        return;
    }

    OpenNIT.fetch('/admin/roles/' + roleId + '/delete', {
        method: 'POST'
    })
    .then(function(response) {
        return response.json();
    })
    .then(function(data) {
        if (data.success) {
            OpenNIT.notify(window.onitText('Rolle gelöscht'), 'success');
            window.location.href = '/admin/roles';
        } else {
            OpenNIT.notify(data.error || window.onitText('Fehler beim Löschen'), 'error');
        }
    })
    .catch(function() {
        OpenNIT.notify(window.onitText('Fehler beim Löschen'), 'error');
    });
};

/**
 * Audit-Export
 */
OpenNIT.Admin.exportAudit = function(format) {
    const params = new URLSearchParams(window.location.search);
    params.set('format', format);
    window.location.href = '/admin/audit/export?' + params.toString();
};

/**
 * Hash-Kette verifizieren
 */
OpenNIT.Admin.verifyHashChain = function(startId, limit) {
    const button = document.querySelector('.verify-btn');
    if (button) {
        button.disabled = true;
        button.textContent = 'Verifiziere...';
    }

    OpenNIT.fetch('/admin/audit/verify?start_id=' + startId + '&limit=' + limit)
    .then(function(response) {
        return response.json();
    })
    .then(function(data) {
        if (data.valid) {
            OpenNIT.notify(window.onitText('Alle {anzahl} Einträge sind integer').replace('{anzahl}', data.verified_count), 'success');
        } else {
            OpenNIT.notify(window.onitText('Integritätsfehler bei {anzahl} Einträgen gefunden!').replace('{anzahl}', data.error_count), 'error');
        }
        if (button) {
            button.disabled = false;
            button.textContent = 'Verifizieren';
        }
    })
    .catch(function() {
        OpenNIT.notify('Fehler bei der Verifizierung', 'error');
        if (button) {
            button.disabled = false;
            button.textContent = 'Verifizieren';
        }
    });
};

/**
 * Berechtigungs-Matrix Toggle
 */
OpenNIT.Admin.togglePermission = function(userId, topicId, roleId, checkbox) {
    const action = checkbox.checked ? 'grant' : 'revoke';

    OpenNIT.fetch('/admin/permissions/' + action, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            user_id: userId,
            topic_id: topicId,
            role_id: roleId
        })
    })
    .then(function(response) {
        return response.json();
    })
    .then(function(data) {
        if (data.success) {
            OpenNIT.notify(action === 'grant' ? 'Berechtigung erteilt' : 'Berechtigung entzogen', 'success');
        } else {
            checkbox.checked = !checkbox.checked; // Zurücksetzen
            OpenNIT.notify(data.error || 'Fehler', 'error');
        }
    })
    .catch(function() {
        checkbox.checked = !checkbox.checked; // Zurücksetzen
        OpenNIT.notify('Fehler beim Speichern', 'error');
    });
};

/**
 * Review-Status aktualisieren
 */
OpenNIT.Admin.completeReview = function(pageId, button) {
    if (!confirm('Review als abgeschlossen markieren?')) {
        return;
    }

    button.disabled = true;
    button.textContent = 'Wird gespeichert...';

    OpenNIT.fetch('/pages/' + pageId + '/responsibilities/complete-review', {
        method: 'POST'
    })
    .then(function(response) {
        return response.json();
    })
    .then(function(data) {
        if (data.success) {
            OpenNIT.notify('Review abgeschlossen', 'success');
            window.location.reload();
        } else {
            button.disabled = false;
            button.textContent = window.onitText('Review abschließen');
            OpenNIT.notify(data.error || 'Fehler', 'error');
        }
    })
    .catch(function() {
        button.disabled = false;
        button.textContent = window.onitText('Review abschließen');
        OpenNIT.notify('Fehler beim Speichern', 'error');
    });
};