Fix: Tab-Navigation + Umlaute in app.js

sourceSubTabs vom Haupt-Navigation-Handler ausgeschlossen -
verhindert dass Source-Sub-Tabs die Hauptnavigation stören
und Inhalte unterhalb anderer Tabs angezeigt werden.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
claude-dev
2026-03-08 16:38:26 +01:00
Ursprung 75dd9b0669
Commit fb5ed358bd

Datei anzeigen

@@ -54,10 +54,10 @@ function logout() {
// --- Navigation ---
function setupNavTabs() {
document.querySelectorAll(".nav-tabs:not(#orgDetailTabs) .nav-tab").forEach(tab => {
document.querySelectorAll(".nav-tabs:not(#orgDetailTabs):not(#sourceSubTabs) .nav-tab").forEach(tab => {
tab.addEventListener("click", () => {
const section = tab.dataset.section;
document.querySelectorAll(".nav-tabs:not(#orgDetailTabs) .nav-tab").forEach(t => t.classList.remove("active"));
document.querySelectorAll(".nav-tabs:not(#orgDetailTabs):not(#sourceSubTabs) .nav-tab").forEach(t => t.classList.remove("active"));
tab.classList.add("active");
document.querySelectorAll(".app-content > .section").forEach(s => s.classList.remove("active"));
document.getElementById(`sec-${section}`).classList.add("active");
@@ -106,7 +106,7 @@ async function loadDashboard() {
<div class="stat-value">${stats.licenses.active}</div>
</div>
<div class="stat-card">
<div class="stat-label">Vorfaelle</div>
<div class="stat-label">Vorfälle</div>
<div class="stat-value">${stats.incidents.total}</div>
<div class="stat-sub">${stats.incidents.active} aktiv</div>
</div>
@@ -128,7 +128,7 @@ async function loadDashboard() {
// Recent activity
const actEl = document.getElementById("recentActivity");
if (stats.recent_activity.length === 0) {
actEl.innerHTML = '<div class="text-muted">Keine Aktivitaet</div>';
actEl.innerHTML = '<div class="text-muted">Keine Aktivität</div>';
} else {
actEl.innerHTML = stats.recent_activity.map(a => `
<div class="activity-item">
@@ -250,7 +250,7 @@ async function loadOrgUsers(orgId) {
? `<button class="btn btn-secondary btn-small" onclick="toggleUser(${u.id}, false)">Deaktivieren</button>`
: `<button class="btn btn-success btn-small" onclick="toggleUser(${u.id}, true)">Aktivieren</button>`
}
<button class="btn btn-danger btn-small" onclick="confirmDeleteUser(${u.id}, '${esc(u.email)}')">Loeschen</button>
<button class="btn btn-danger btn-small" onclick="confirmDeleteUser(${u.id}, '${esc(u.email)}')">Löschen</button>
</td>
</tr>
`).join("");
@@ -279,8 +279,8 @@ async function toggleUser(userId, activate) {
function confirmDeleteUser(userId, email) {
showConfirm(
"Nutzer loeschen",
`Soll der Nutzer "${email}" endgueltig geloescht werden?`,
"Nutzer löschen",
`Soll der Nutzer "${email}" endgültig gelöscht werden?`,
async () => {
try {
await API.del(`/api/users/${userId}`);
@@ -310,7 +310,7 @@ async function loadOrgLicenses(orgId) {
<td><span class="badge badge-${l.status}">${l.status}</span></td>
<td>
${l.status === "active" ? `
<button class="btn btn-secondary btn-small" onclick="extendLicense(${l.id})">Verlaengern</button>
<button class="btn btn-secondary btn-small" onclick="extendLicense(${l.id})">Verlängern</button>
<button class="btn btn-danger btn-small" onclick="confirmRevokeLicense(${l.id})">Widerrufen</button>
` : ""}
</td>
@@ -322,7 +322,7 @@ async function loadOrgLicenses(orgId) {
}
async function extendLicense(licId) {
const days = prompt("Um wie viele Tage verlaengern?", "365");
const days = prompt("Um wie viele Tage verlängern?", "365");
if (!days) return;
try {
await API.put(`/api/licenses/${licId}/extend?days=${parseInt(days)}`);
@@ -335,7 +335,7 @@ async function extendLicense(licId) {
function confirmRevokeLicense(licId) {
showConfirm(
"Lizenz widerrufen",
"Soll die Lizenz wirklich widerrufen werden? Nutzer koennen dann nur noch lesen.",
"Soll die Lizenz wirklich widerrufen werden? Nutzer können dann nur noch lesen.",
async () => {
try {
await API.put(`/api/licenses/${licId}/revoke`);
@@ -354,7 +354,7 @@ async function loadExpiringLicenses() {
const licenses = await API.get(`/api/licenses/expiring?days=${days}`);
const tbody = document.getElementById("expiringTable");
if (licenses.length === 0) {
tbody.innerHTML = `<tr><td colspan="5" class="text-muted">Keine ablaufenden Lizenzen in den naechsten ${days} Tagen</td></tr>`;
tbody.innerHTML = `<tr><td colspan="5" class="text-muted">Keine ablaufenden Lizenzen in den nächsten ${days} Tagen</td></tr>`;
return;
}
tbody.innerHTML = licenses.map(l => `
@@ -364,7 +364,7 @@ async function loadExpiringLicenses() {
<td>${l.max_users}</td>
<td class="text-warning">${formatDate(l.valid_until)}</td>
<td>
<button class="btn btn-secondary btn-small" onclick="extendLicense(${l.id})">Verlaengern</button>
<button class="btn btn-secondary btn-small" onclick="extendLicense(${l.id})">Verlängern</button>
</td>
</tr>
`).join("");
@@ -380,7 +380,7 @@ document.addEventListener("DOMContentLoaded", () => {
function switchToOrg(orgId) {
// Switch to orgs tab and open detail
document.querySelectorAll(".nav-tabs:not(#orgDetailTabs) .nav-tab").forEach(t => t.classList.remove("active"));
document.querySelectorAll(".nav-tabs:not(#orgDetailTabs):not(#sourceSubTabs) .nav-tab").forEach(t => t.classList.remove("active"));
document.querySelector('.nav-tab[data-section="orgs"]').classList.add("active");
document.querySelectorAll(".app-content > .section").forEach(s => s.classList.remove("active"));
document.getElementById("sec-orgs").classList.add("active");
@@ -495,8 +495,8 @@ function setupForms() {
// Delete Org
document.getElementById("deleteOrgBtn").addEventListener("click", () => {
showConfirm(
"Organisation loeschen",
"Soll die Organisation mit allen Nutzern und Lizenzen endgueltig geloescht werden? Diese Aktion kann nicht rueckgaengig gemacht werden.",
"Organisation löschen",
"Soll die Organisation mit allen Nutzern und Lizenzen endgültig gelöscht werden? Diese Aktion kann nicht rückgängig gemacht werden.",
async () => {
try {
await API.del(`/api/orgs/${currentOrgId}`);