|
|
|
@@ -314,7 +314,13 @@ function renderOrgHeader(org) {
|
|
|
|
document.getElementById("orgDetailHeader").innerHTML = `
|
|
|
|
document.getElementById("orgDetailHeader").innerHTML = `
|
|
|
|
<div style="display:flex; align-items:flex-start; gap:10px; flex-wrap:wrap;">
|
|
|
|
<div style="display:flex; align-items:flex-start; gap:10px; flex-wrap:wrap;">
|
|
|
|
<div style="flex:1; min-width:260px;">
|
|
|
|
<div style="flex:1; min-width:260px;">
|
|
|
|
<h2>${esc(org.name)} <span class="badge badge-${org.is_active ? 'active' : 'inactive'}" style="font-size: 12px; vertical-align: middle;">${org.is_active ? "Aktiv" : "Inaktiv"}</span></h2>
|
|
|
|
<h2 style="display:flex; align-items:center; gap:10px; flex-wrap:wrap;">${esc(org.name)}
|
|
|
|
|
|
|
|
<select onchange="setOrgActive(this.value)" title="Status der Organisation, speichert sofort"
|
|
|
|
|
|
|
|
style="width:auto; font-size:13px; padding:4px 8px;">
|
|
|
|
|
|
|
|
<option value="true"${org.is_active ? " selected" : ""}>Aktiv</option>
|
|
|
|
|
|
|
|
<option value="false"${org.is_active ? "" : " selected"}>Deaktiviert</option>
|
|
|
|
|
|
|
|
</select>
|
|
|
|
|
|
|
|
</h2>
|
|
|
|
<div class="text-secondary mt-8">Slug: ${esc(org.slug)} | Nutzer: ${org.user_count} | Lizenz: ${org.license_type || "Keine"} | Kontingent: <span id="orgKpiCredits">${esc(kpiText)}</span></div>
|
|
|
|
<div class="text-secondary mt-8">Slug: ${esc(org.slug)} | Nutzer: ${org.user_count} | Lizenz: ${org.license_type || "Keine"} | Kontingent: <span id="orgKpiCredits">${esc(kpiText)}</span></div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<button class="btn btn-secondary btn-small" onclick="renameOrg()" title="Organisation umbenennen">
|
|
|
|
<button class="btn btn-secondary btn-small" onclick="renameOrg()" title="Organisation umbenennen">
|
|
|
|
@@ -375,6 +381,25 @@ function setOrgLanguage(wert) {
|
|
|
|
_saveOrgSetting({ output_language: wert }, "Pipeline-Sprache gespeichert");
|
|
|
|
_saveOrgSetting({ output_language: wert }, "Pipeline-Sprache gespeichert");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Max Nutzer der aktiven Lizenz direkt in der Tabelle ändern
|
|
|
|
|
|
|
|
async function setLicenseMaxUsers(licId, wert) {
|
|
|
|
|
|
|
|
const n = parseInt(wert, 10);
|
|
|
|
|
|
|
|
if (!n || n < 1 || n > 1000) {
|
|
|
|
|
|
|
|
showToast("Max Nutzer muss zwischen 1 und 1000 liegen", "error");
|
|
|
|
|
|
|
|
loadOrgLicenses(currentOrgId);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
await API.put(`/api/token-usage/budget/${licId}`, { max_users: n });
|
|
|
|
|
|
|
|
showToast("Maximale Nutzerzahl gespeichert", "success");
|
|
|
|
|
|
|
|
loadOrgLicenses(currentOrgId);
|
|
|
|
|
|
|
|
loadOrgUsers(currentOrgId); // Limit-Anzeige über der Nutzerliste zieht mit
|
|
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
|
|
showToast(err.message, "error");
|
|
|
|
|
|
|
|
loadOrgLicenses(currentOrgId);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renameOrg() {
|
|
|
|
function renameOrg() {
|
|
|
|
const input = document.getElementById("renameOrgName");
|
|
|
|
const input = document.getElementById("renameOrgName");
|
|
|
|
const errEl = document.getElementById("renameOrgError");
|
|
|
|
const errEl = document.getElementById("renameOrgError");
|
|
|
|
@@ -506,17 +531,13 @@ async function loadOrgLicenses(orgId) {
|
|
|
|
const licenses = await API.get(`/api/licenses?org_id=${orgId}`);
|
|
|
|
const licenses = await API.get(`/api/licenses?org_id=${orgId}`);
|
|
|
|
const tbody = document.getElementById("licenseTable");
|
|
|
|
const tbody = document.getElementById("licenseTable");
|
|
|
|
if (licenses.length === 0) {
|
|
|
|
if (licenses.length === 0) {
|
|
|
|
tbody.innerHTML = '<tr><td colspan="8" class="text-muted">Keine Lizenzen</td></tr>';
|
|
|
|
tbody.innerHTML = '<tr><td colspan="7" class="text-muted">Keine Lizenzen</td></tr>';
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Org-Status und Pipeline-Sprache sind Org-Einstellungen und stehen nur in
|
|
|
|
// Pipeline-Sprache ist eine Org-Einstellung und steht nur in der aktiven
|
|
|
|
// der aktiven Zeile, direkt umschaltbar (Sofort-Speicherung).
|
|
|
|
// Zeile (Sofort-Speicherung). Max Nutzer ist dort direkt editierbar.
|
|
|
|
const org = currentOrgData || {};
|
|
|
|
const org = currentOrgData || {};
|
|
|
|
const orgZellen = `
|
|
|
|
const spracheZelle = `
|
|
|
|
<td><select style="width:auto; min-width:110px;" onchange="setOrgActive(this.value)">
|
|
|
|
|
|
|
|
<option value="true"${org.is_active ? " selected" : ""}>Aktiv</option>
|
|
|
|
|
|
|
|
<option value="false"${org.is_active ? "" : " selected"}>Deaktiviert</option>
|
|
|
|
|
|
|
|
</select></td>
|
|
|
|
|
|
|
|
<td><select style="width:auto; min-width:100px;" onchange="setOrgLanguage(this.value)" title="Ausgabesprache der KI-Pipeline für alle Nutzer dieser Organisation">
|
|
|
|
<td><select style="width:auto; min-width:100px;" onchange="setOrgLanguage(this.value)" title="Ausgabesprache der KI-Pipeline für alle Nutzer dieser Organisation">
|
|
|
|
<option value="de"${(org.output_language || "de") === "de" ? " selected" : ""}>Deutsch</option>
|
|
|
|
<option value="de"${(org.output_language || "de") === "de" ? " selected" : ""}>Deutsch</option>
|
|
|
|
<option value="en"${org.output_language === "en" ? " selected" : ""}>English</option>
|
|
|
|
<option value="en"${org.output_language === "en" ? " selected" : ""}>English</option>
|
|
|
|
@@ -524,11 +545,14 @@ async function loadOrgLicenses(orgId) {
|
|
|
|
tbody.innerHTML = licenses.map(l => `
|
|
|
|
tbody.innerHTML = licenses.map(l => `
|
|
|
|
<tr>
|
|
|
|
<tr>
|
|
|
|
<td><span class="badge badge-${l.license_type}">${l.license_type}</span></td>
|
|
|
|
<td><span class="badge badge-${l.license_type}">${l.license_type}</span></td>
|
|
|
|
<td>${l.max_users}</td>
|
|
|
|
<td>${l.status === "active"
|
|
|
|
|
|
|
|
? `<input type="number" value="${l.max_users}" min="1" max="1000" style="width:70px;"
|
|
|
|
|
|
|
|
onchange="setLicenseMaxUsers(${l.id}, this.value)" title="Maximale Nutzerzahl, speichert sofort">`
|
|
|
|
|
|
|
|
: l.max_users}</td>
|
|
|
|
<td>${formatDate(l.valid_from)}</td>
|
|
|
|
<td>${formatDate(l.valid_from)}</td>
|
|
|
|
<td>${l.valid_until ? formatDate(l.valid_until) : "Unbegrenzt"}</td>
|
|
|
|
<td>${l.valid_until ? formatDate(l.valid_until) : "Unbegrenzt"}</td>
|
|
|
|
<td><span class="badge badge-${l.status}">${l.status}</span></td>
|
|
|
|
<td><span class="badge badge-${l.status}">${l.status}</span></td>
|
|
|
|
${l.status === "active" ? orgZellen : '<td class="text-muted">–</td><td class="text-muted">–</td>'}
|
|
|
|
${l.status === "active" ? spracheZelle : '<td class="text-muted">–</td>'}
|
|
|
|
<td>
|
|
|
|
<td>
|
|
|
|
${l.status === "active" ? `
|
|
|
|
${l.status === "active" ? `
|
|
|
|
<button class="btn btn-secondary btn-small" onclick="extendLicense(${l.id})">Verlängern</button>
|
|
|
|
<button class="btn btn-secondary btn-small" onclick="extendLicense(${l.id})">Verlängern</button>
|
|
|
|
|