diff --git a/src/static/dashboard.html b/src/static/dashboard.html index 8ce0952..358b00b 100644 --- a/src/static/dashboard.html +++ b/src/static/dashboard.html @@ -118,7 +118,6 @@ Name - Slug Nutzer Lizenz Kontingent @@ -523,10 +522,7 @@ Name - - Slug (URL-freundlich) - - + Pipeline-Sprache @@ -1109,7 +1105,7 @@ - + diff --git a/src/static/js/app.js b/src/static/js/app.js index cd37ea2..241ec57 100644 --- a/src/static/js/app.js +++ b/src/static/js/app.js @@ -253,13 +253,12 @@ function orgUsageCell(orgId) { function renderOrgTable(orgs) { const tbody = document.getElementById("orgTable"); if (orgs.length === 0) { - tbody.innerHTML = 'Keine Organisationen'; + tbody.innerHTML = 'Keine Organisationen'; return; } tbody.innerHTML = orgs.map(o => ` ${esc(o.name)} - ${esc(o.slug)} ${o.user_count} ${o.license_type || "Keine"} ${orgUsageCell(o.id)} @@ -289,8 +288,6 @@ document.addEventListener("DOMContentLoaded", () => { let currentOrgData = null; // zuletzt geladene Org (fuer Inline-Einstellungen) function renderOrgHeader(org) { - const kpiAlt = document.getElementById("orgKpiCredits"); - const kpiText = kpiAlt ? kpiAlt.textContent : "wird geladen …"; document.getElementById("orgDetailHeader").innerHTML = ` @@ -306,7 +303,6 @@ function renderOrgHeader(org) { - Slug: ${esc(org.slug)} | Nutzer: ${org.user_count} | Lizenz: ${org.license_type || "Keine"} | Kontingent: ${esc(kpiText)} @@ -668,9 +664,13 @@ function setupForms() { e.preventDefault(); const errEl = document.getElementById("newOrgError"); errEl.style.display = "none"; + // Slug wird unsichtbar aus dem Namen erzeugt, bei Kollision haengt der + // Submit-Handler unten selbststaendig eine Nummer an. + const baseSlug = (document.getElementById("newOrgSlug").value || + document.getElementById("newOrgName").value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")) || "organisation"; const body = { name: document.getElementById("newOrgName").value, - slug: document.getElementById("newOrgSlug").value, + slug: baseSlug, output_language: document.getElementById("newOrgLanguage").value || "de", }; // Optional direkt eine Lizenz mit Credits-Kontingent mitgeben @@ -698,7 +698,16 @@ function setupForms() { body.license = lic; } try { - await API.post("/api/orgs", body); + let angelegt = false; + for (let i = 0; i < 8 && !angelegt; i++) { + body.slug = i === 0 ? baseSlug : baseSlug + "-" + (i + 1); + try { + await API.post("/api/orgs", body); + angelegt = true; + } catch (err) { + if (!(err.message || "").includes("Slug bereits vergeben") || i === 7) throw err; + } + } closeModal("modalNewOrg"); document.getElementById("newOrgForm").reset(); onNewOrgLicenseToggle(); @@ -1100,16 +1109,6 @@ async function loadOrgTokenUsage(orgId) { fillBudgetForm(budget); - // Kontingent-Kurzinfo im Org-Kopf - const kpi = document.getElementById("orgKpiCredits"); - if (kpi) { - if (unlimited) kpi.textContent = "unbegrenzt"; - else if (budget.credits_available) { - const pct = budget.credits_percent_used != null ? ` (${budget.credits_percent_used.toFixed(0)}% verbraucht)` : ""; - kpi.textContent = `${Math.round(budget.credits_used || 0).toLocaleString("de-DE")} von ${Math.round(budget.credits_available).toLocaleString("de-DE")} Credits${pct}`; - } else kpi.textContent = "kein Kontingent"; - } - const tbody = document.getElementById('tokenMonthlyTable'); if (tbody) { tbody.innerHTML = monthly.map(function(m) {