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:
@@ -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}`);
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren